Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/mips emulate the special3 opcode LX (lwx, ldx, lhx, ...



details:   https://anonhg.NetBSD.org/src/rev/32996fff9fe3
branches:  trunk
changeset: 768450:32996fff9fe3
user:      matt <matt%NetBSD.org@localhost>
date:      Wed Aug 17 06:59:28 2011 +0000

description:
emulate the special3 opcode LX (lwx, ldx, lhx, lbux) instructions.

diffstat:

 sys/arch/mips/include/mips_opcode.h |   8 ++++-
 sys/arch/mips/mips/mips_emul.c      |  58 +++++++++++++++++++++++++++++++++++-
 2 files changed, 63 insertions(+), 3 deletions(-)

diffs (110 lines):

diff -r a42682966a82 -r 32996fff9fe3 sys/arch/mips/include/mips_opcode.h
--- a/sys/arch/mips/include/mips_opcode.h       Wed Aug 17 05:32:09 2011 +0000
+++ b/sys/arch/mips/include/mips_opcode.h       Wed Aug 17 06:59:28 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mips_opcode.h,v 1.16 2011/03/15 07:33:54 matt Exp $    */
+/*     $NetBSD: mips_opcode.h,v 1.17 2011/08/17 06:59:28 matt Exp $    */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -266,8 +266,14 @@
 /*
  * Values for the 'func' field when 'op' == OP_SPECIAL3.
  */
+#define        OP_LX           012             /* DSP */
 #define OP_RDHWR       073             /* MIPS32/64 r2 */
 
+#define        OP_LX_LWX       0               /* lwx */
+#define        OP_LX_LHX       4               /* lhx */
+#define        OP_LX_LBUX      6               /* lbux */
+#define        OP_LX_LDX       8               /* ldx */
+
 /*
  * Values for the 'func' field when 'op' == OP_BCOND.
  */
diff -r a42682966a82 -r 32996fff9fe3 sys/arch/mips/mips/mips_emul.c
--- a/sys/arch/mips/mips/mips_emul.c    Wed Aug 17 05:32:09 2011 +0000
+++ b/sys/arch/mips/mips/mips_emul.c    Wed Aug 17 06:59:28 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mips_emul.c,v 1.23 2011/03/15 07:39:23 matt Exp $ */
+/*     $NetBSD: mips_emul.c,v 1.24 2011/08/17 06:59:29 matt Exp $ */
 
 /*
  * Copyright (c) 1999 Shuichiro URATA.  All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.23 2011/03/15 07:39:23 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.24 2011/08/17 06:59:29 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -399,6 +399,59 @@
        ksiginfo_t ksi;
        const InstFmt instfmt = { .word = inst };
        switch (instfmt.RType.func) {
+       case OP_LX: {
+               const intptr_t vaddr = tf->tf_regs[instfmt.RType.rs] 
+                   + tf->tf_regs[instfmt.RType.rt];
+               mips_reg_t r;
+               int error = EFAULT;
+               if (vaddr < 0) {
+                   addr_err:
+                       send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
+                       return;
+               }
+               switch (instfmt.RType.shamt) {
+#if !defined(__mips_o32)
+               case OP_LX_LDX: {
+                       uint64_t tmp64;
+                       if (vaddr & 7)
+                               goto addr_err;
+                       error = copyin((void *)vaddr, &tmp64, sizeof(tmp64));
+                       r = tmp64;
+                       break;
+               }
+#endif
+               case OP_LX_LWX: {
+                       int32_t tmp32;
+                       if (vaddr & 3)
+                               goto addr_err;
+                       error = copyin((void *)vaddr, &tmp32, sizeof(tmp32));
+                       r = tmp32;
+                       break;
+               }
+               case OP_LX_LHX: {
+                       int16_t tmp16;
+                       if (vaddr & 1)
+                               goto addr_err;
+                       error = copyin((void *)vaddr, &tmp16, sizeof(tmp16));
+                       r = tmp16;
+                       break;
+               }
+               case OP_LX_LBUX: {
+                       uint8_t tmp8;
+                       error = copyin((void *)vaddr, &tmp8, sizeof(tmp8));
+                       r = tmp8;
+                       break;
+               }
+               default:
+                       goto illopc;
+               }
+               if (error) {
+                       send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
+                       return;
+               }
+               tf->tf_regs[instfmt.RType.rd] = r;
+               break;
+       }
        case OP_RDHWR:
                switch (instfmt.RType.rd) {
                case 29:
@@ -407,6 +460,7 @@
                        break;
                }
                /* FALLTHROUGH */
+       illopc:
        default:
                tf->tf_regs[_R_CAUSE] = cause;
                tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC];



Home | Main Index | Thread Index | Old Index