drc: emulate break opcode
authornotaz <notasas@gmail.com>
Wed, 26 Jan 2022 20:09:22 +0000 (22:09 +0200)
committernotaz <notasas@gmail.com>
Fri, 28 Jan 2022 00:04:32 +0000 (02:04 +0200)
sort-of-but-not-really used by "F1 2000"
(SLUS01120, not "Formula One 2000").

libpcsxcore/new_dynarec/linkage_arm.S
libpcsxcore/new_dynarec/linkage_arm64.S
libpcsxcore/new_dynarec/new_dynarec.c

index d409aff..5538462 100644 (file)
@@ -34,6 +34,7 @@
 #define gen_interupt           ESYM(gen_interupt)
 #define invalidate_addr                ESYM(invalidate_addr)
 #define gteCheckStallRaw       ESYM(gteCheckStallRaw)
+#define psxException           ESYM(psxException)
 #endif
 
        .bss
@@ -497,19 +498,28 @@ FUNCTION(fp_exception_ds):
        .size   fp_exception_ds, .-fp_exception_ds
 
        .align  2
+FUNCTION(jump_break_ds):
+       mov     r0, #0x24
+       mov     r1, #1
+       b       call_psxException
+FUNCTION(jump_break):
+       mov     r0, #0x24
+       mov     r1, #0
+       b       call_psxException
+FUNCTION(jump_syscall_ds):
+       mov     r0, #0x20
+       mov     r1, #1
+       b       call_psxException
 FUNCTION(jump_syscall):
-       ldr     r1, [fp, #LO_reg_cop0+48] /* Status */
-       mov     r3, #0x80000000
-       str     r0, [fp, #LO_reg_cop0+56] /* EPC */
-       orr     r1, #2
-       mov     r2, #0x20
-       str     r1, [fp, #LO_reg_cop0+48] /* Status */
-       str     r2, [fp, #LO_reg_cop0+52] /* Cause */
-       add     r0, r3, #0x80
-       bl      get_addr_ht
-       mov     pc, r0
-       .size   jump_syscall, .-jump_syscall
-       .align  2
+       mov     r0, #0x20
+       mov     r1, #0
+
+call_psxException:
+       ldr     r3, [fp, #LO_last_count]
+       str     r2, [fp, #LO_pcaddr]
+       add     r10, r3, r10
+       str     r10, [fp, #LO_cycle]            /* PCSX cycles */
+       bl      psxException
 
        /* note: psxException might do recursive recompiler call from it's HLE code,
         * so be ready for this */
index b9ab726..39e95a8 100644 (file)
@@ -182,19 +182,28 @@ FUNCTION(fp_exception_ds):
        .size   fp_exception_ds, .-fp_exception_ds
 
        .align  2
+FUNCTION(jump_break_ds):
+       mov     w0, #0x24
+       mov     w1, #1
+       b       call_psxException
+FUNCTION(jump_break):
+       mov     w0, #0x24
+       mov     w1, #0
+       b       call_psxException
+FUNCTION(jump_syscall_ds):
+       mov     w0, #0x20
+       mov     w1, #1
+       b       call_psxException
 FUNCTION(jump_syscall):
-       ldr     w1, [rFP, #LO_reg_cop0+48] /* Status */
-       mov     w3, #0x80000000
-       str     w0, [rFP, #LO_reg_cop0+56] /* EPC */
-       orr     w1, w1, #2
-       mov     w2, #0x20
-       str     w1, [rFP, #LO_reg_cop0+48] /* Status */
-       str     w2, [rFP, #LO_reg_cop0+52] /* Cause */
-       add     w0, w3, #0x80
-       bl      get_addr_ht
-       br      x0
-       .size   jump_syscall, .-jump_syscall
-       .align  2
+       mov     w0, #0x20
+       mov     w1, #0
+
+call_psxException:
+       ldr     w3, [rFP, #LO_last_count]
+       str     w2, [rFP, #LO_pcaddr]
+       add     rCC, w3, rCC
+       str     rCC, [rFP, #LO_cycle]           /* PCSX cycles */
+       bl      psxException
 
        /* note: psxException might do recursive recompiler call from it's HLE code,
         * so be ready for this */
index 107a630..2ca0f60 100644 (file)
@@ -49,6 +49,7 @@
 
 //#define DISASM
 //#define ASSEM_PRINT
+//#define REG_ALLOC_PRINT
 
 #ifdef ASSEM_PRINT
 #define assem_debug printf
@@ -297,7 +298,7 @@ static struct decoded_insn
 //#define FLOAT 19  // Floating point unit
 //#define FCONV 20  // Convert integer to float
 //#define FCOMP 21  // Floating point compare (sets FSREG)
-#define SYSCALL 22// SYSCALL
+#define SYSCALL 22// SYSCALL,BREAK
 #define OTHER 23  // Other
 #define SPAN 24   // Branch/delay slot spans 2 pages
 #define NI 25     // Not implemented
@@ -328,6 +329,10 @@ void verify_code_ds();
 void cc_interrupt();
 void fp_exception();
 void fp_exception_ds();
+void jump_syscall   (u_int u0, u_int u1, u_int pc);
+void jump_syscall_ds(u_int u0, u_int u1, u_int pc);
+void jump_break   (u_int u0, u_int u1, u_int pc);
+void jump_break_ds(u_int u0, u_int u1, u_int pc);
 void jump_to_new_pc();
 void call_gteStall();
 void new_dyna_leave();
@@ -926,6 +931,10 @@ static const struct {
   FUNCNAME(jump_handler_write32),
   FUNCNAME(invalidate_addr),
   FUNCNAME(jump_to_new_pc),
+  FUNCNAME(jump_break),
+  FUNCNAME(jump_break_ds),
+  FUNCNAME(jump_syscall),
+  FUNCNAME(jump_syscall_ds),
   FUNCNAME(call_gteStall),
   FUNCNAME(new_dyna_leave),
   FUNCNAME(pcsx_mtc0),
@@ -3935,9 +3944,16 @@ static void call_c_cpu_handler(int i, const struct regstat *i_regs, int ccadj_,
 
 static void syscall_assemble(int i, const struct regstat *i_regs, int ccadj_)
 {
-  emit_movimm(0x20,0); // cause code
-  emit_movimm(0,1);    // not in delay slot
-  call_c_cpu_handler(i, i_regs, ccadj_, start+i*4, psxException);
+  // 'break' tends to be littered around to catch things like
+  // division by 0 and is almost never executed, so don't emit much code here
+  void *func = (dops[i].opcode2 == 0x0C)
+    ? (is_delayslot ? jump_syscall_ds : jump_syscall)
+    : (is_delayslot ? jump_break_ds : jump_break);
+  signed char ccreg = get_reg(i_regs->regmap, CCREG);
+  assert(ccreg == HOST_CCREG);
+  emit_movimm(start + i*4, 2); // pc
+  emit_addimm(HOST_CCREG, ccadj_ + CLOCK_ADJUST(1), HOST_CCREG);
+  emit_far_jump(func);
 }
 
 static void hlecall_assemble(int i, const struct regstat *i_regs, int ccadj_)
@@ -7200,7 +7216,7 @@ int new_recompile_block(u_int addr)
           case 0x08: strcpy(insn[i],"JR"); type=RJUMP; break;
           case 0x09: strcpy(insn[i],"JALR"); type=RJUMP; break;
           case 0x0C: strcpy(insn[i],"SYSCALL"); type=SYSCALL; break;
-          case 0x0D: strcpy(insn[i],"BREAK"); type=OTHER; break;
+          case 0x0D: strcpy(insn[i],"BREAK"); type=SYSCALL; break;
           case 0x0F: strcpy(insn[i],"SYNC"); type=OTHER; break;
           case 0x10: strcpy(insn[i],"MFHI"); type=MOV; break;
           case 0x11: strcpy(insn[i],"MTHI"); type=MOV; break;
@@ -7646,9 +7662,9 @@ int new_recompile_block(u_int addr)
       // Don't get too close to the limit
       if(i>MAXBLOCK/2) done=1;
     }
-    if(dops[i].itype==SYSCALL&&stop_after_jal) done=1;
-    if(dops[i].itype==HLECALL||dops[i].itype==INTCALL) done=2;
-    if(done==2) {
+    if (dops[i].itype == SYSCALL || dops[i].itype == HLECALL || dops[i].itype == INTCALL)
+      done = stop_after_jal ? 1 : 2;
+    if (done == 2) {
       // Does the block continue due to a branch?
       for(j=i-1;j>=0;j--)
       {
@@ -9021,7 +9037,7 @@ int new_recompile_block(u_int addr)
     dops[slen-1].bt=1; // Mark as a branch target so instruction can restart after exception
   }
 
-#ifdef DISASM
+#ifdef REG_ALLOC_PRINT
   /* Debug/disassembly */
   for(i=0;i<slen;i++)
   {
@@ -9153,7 +9169,7 @@ int new_recompile_block(u_int addr)
       #endif
     }
   }
-#endif // DISASM
+#endif // REG_ALLOC_PRINT
 
   /* Pass 8 - Assembly */
   linkcount=0;stubcount=0;