From d1150cd66676ce43b8451c65818c2dc3e2f8a1d6 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 26 Jan 2022 22:09:22 +0200 Subject: [PATCH] drc: emulate break opcode sort-of-but-not-really used by "F1 2000" (SLUS01120, not "Formula One 2000"). --- libpcsxcore/new_dynarec/linkage_arm.S | 34 ++++++++++++++--------- libpcsxcore/new_dynarec/linkage_arm64.S | 33 ++++++++++++++--------- libpcsxcore/new_dynarec/new_dynarec.c | 36 ++++++++++++++++++------- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/libpcsxcore/new_dynarec/linkage_arm.S b/libpcsxcore/new_dynarec/linkage_arm.S index d409aff5..5538462f 100644 --- a/libpcsxcore/new_dynarec/linkage_arm.S +++ b/libpcsxcore/new_dynarec/linkage_arm.S @@ -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 */ diff --git a/libpcsxcore/new_dynarec/linkage_arm64.S b/libpcsxcore/new_dynarec/linkage_arm64.S index b9ab726b..39e95a83 100644 --- a/libpcsxcore/new_dynarec/linkage_arm64.S +++ b/libpcsxcore/new_dynarec/linkage_arm64.S @@ -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 */ diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 107a6304..2ca0f604 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -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