32x: drc: emulate illegal insn
authornotaz <notasas@gmail.com>
Sun, 11 Aug 2013 21:47:25 +0000 (00:47 +0300)
committernotaz <notasas@gmail.com>
Wed, 14 Aug 2013 00:37:45 +0000 (03:37 +0300)
The X-Men proto debugger makes it worth it

cpu/sh2/compiler.c

index 103f286..106fab5 100644 (file)
@@ -1228,7 +1228,7 @@ static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int siz
   return hr2;
 }
 
-static void emit_memhandler_write(int size, u32 pc)
+static void emit_memhandler_write(int size)
 {
   int ctxr;
   host_arg2reg(ctxr, 2);
@@ -1718,7 +1718,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         tmp2 = rcache_get_reg_arg(0, SHR_R0);
         tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
         emith_add_r_r(tmp2, tmp3);
-        emit_memhandler_write(op & 3, pc);
+        emit_memhandler_write(op & 3);
         goto end_op;
       case 0x07:
         // MUL.L     Rm,Rn      0000nnnnmmmm0111
@@ -1837,7 +1837,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
       tmp2 = rcache_get_reg_arg(1, GET_Rm());
       if (op & 0x0f)
         emith_add_r_imm(tmp, (op & 0x0f) * 4);
-      emit_memhandler_write(2, pc);
+      emit_memhandler_write(2);
       goto end_op;
 
     case 0x02:
@@ -1849,7 +1849,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         rcache_clean();
         rcache_get_reg_arg(0, GET_Rn());
         rcache_get_reg_arg(1, GET_Rm());
-        emit_memhandler_write(op & 3, pc);
+        emit_memhandler_write(op & 3);
         goto end_op;
       case 0x04: // MOV.B Rm,@-Rn       0010nnnnmmmm0100
       case 0x05: // MOV.W Rm,@-Rn       0010nnnnmmmm0101
@@ -1859,7 +1859,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         emith_sub_r_imm(tmp, (1 << (op & 3)));
         rcache_clean();
         rcache_get_reg_arg(0, GET_Rn());
-        emit_memhandler_write(op & 3, pc);
+        emit_memhandler_write(op & 3);
         goto end_op;
       case 0x07: // DIV0S Rm,Rn         0010nnnnmmmm0111
         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
@@ -2168,7 +2168,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         tmp3 = rcache_get_reg_arg(1, tmp);
         if (tmp == SHR_SR)
           emith_clear_msb(tmp3, tmp3, 22); // reserved bits defined by ISA as 0
-        emit_memhandler_write(2, pc);
+        emit_memhandler_write(2);
         goto end_op;
       case 0x04:
       case 0x05:
@@ -2308,7 +2308,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
           emith_move_r_r(tmp2, tmp);
           rcache_free_tmp(tmp);
           rcache_get_reg_arg(0, GET_Rn());
-          emit_memhandler_write(0, pc);
+          emit_memhandler_write(0);
           break;
         default:
           goto default_;
@@ -2468,7 +2468,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         tmp3 = (op & 0x100) >> 8;
         if (op & 0x0f)
           emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
-        emit_memhandler_write(tmp3, pc);
+        emit_memhandler_write(tmp3);
         goto end_op;
       case 0x0400: // MOV.B @(disp,Rm),R0  10000100mmmmdddd
       case 0x0500: // MOV.W @(disp,Rm),R0  10000101mmmmdddd
@@ -2501,7 +2501,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         tmp2 = rcache_get_reg_arg(1, SHR_R0);
         tmp3 = (op & 0x300) >> 8;
         emith_add_r_imm(tmp, (op & 0xff) << tmp3);
-        emit_memhandler_write(tmp3, pc);
+        emit_memhandler_write(tmp3);
         goto end_op;
       case 0x0400: // MOV.B @(disp,GBR),R0   11000100dddddddd
       case 0x0500: // MOV.W @(disp,GBR),R0   11000101dddddddd
@@ -2517,12 +2517,12 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         emith_add_r_imm(tmp, 4);
         tmp = rcache_get_reg_arg(1, SHR_SR);
         emith_clear_msb(tmp, tmp, 22);
-        emit_memhandler_write(2, pc);
+        emit_memhandler_write(2);
         // push PC
         rcache_get_reg_arg(0, SHR_SP);
         tmp = rcache_get_tmp_arg(1);
         emith_move_r_imm(tmp, pc);
-        emit_memhandler_write(2, pc);
+        emit_memhandler_write(2);
         // obtain new PC
         emit_memhandler_read_rr(SHR_PC, SHR_VBR, (op & 0xff) * 4, 2);
         // indirect jump -> back to dispatcher
@@ -2574,7 +2574,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
         tmp3 = rcache_get_reg_arg(0, SHR_GBR);
         tmp4 = rcache_get_reg(SHR_R0, RC_GR_READ);
         emith_add_r_r(tmp3, tmp4);
-        emit_memhandler_write(0, pc);
+        emit_memhandler_write(0);
         goto end_op;
       }
       goto default_;
@@ -2587,8 +2587,27 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
 
     default:
     default_:
-      elprintf(EL_ANOMALY, "%csh2 drc: unhandled op %04x @ %08x",
-        sh2->is_slave ? 's' : 'm', op, pc - 2);
+      elprintf_sh2(sh2, EL_ANOMALY,
+        "drc: illegal op %04x @ %08x", op, pc - 2);
+
+      tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
+      emith_sub_r_imm(tmp, 4*2);
+      // push SR
+      tmp = rcache_get_reg_arg(0, SHR_SP);
+      emith_add_r_imm(tmp, 4);
+      tmp = rcache_get_reg_arg(1, SHR_SR);
+      emith_clear_msb(tmp, tmp, 22);
+      emit_memhandler_write(2);
+      // push PC
+      rcache_get_reg_arg(0, SHR_SP);
+      tmp = rcache_get_tmp_arg(1);
+      emith_move_r_imm(tmp, pc - 2);
+      emit_memhandler_write(2);
+      // obtain new PC
+      emit_memhandler_read_rr(SHR_PC, SHR_VBR, 4 * 4, 2);
+      // indirect jump -> back to dispatcher
+      rcache_flush();
+      emith_jump(sh2_drc_dispatcher);
       break;
     }