#define gen_interupt ESYM(gen_interupt)
#define invalidate_addr ESYM(invalidate_addr)
#define gteCheckStallRaw ESYM(gteCheckStallRaw)
+#define psxException ESYM(psxException)
#endif
.bss
.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 */
.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 */
//#define DISASM
//#define ASSEM_PRINT
+//#define REG_ALLOC_PRINT
#ifdef ASSEM_PRINT
#define assem_debug printf
//#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
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();
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),
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_)
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;
// 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--)
{
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++)
{
#endif
}
}
-#endif // DISASM
+#endif // REG_ALLOC_PRINT
/* Pass 8 - Assembly */
linkcount=0;stubcount=0;