Don't ask "useOldPC" and instead just pass the thing

This commit is contained in:
SimoneN64
2023-10-22 20:59:46 +02:00
parent 54b753aa4d
commit 83ba53137c
9 changed files with 103 additions and 103 deletions

View File

@@ -9,21 +9,21 @@ int Interpreter::Step() {
if(check_address_error(0b11, u64(regs.pc))) [[unlikely]] { if(check_address_error(0b11, u64(regs.pc))) [[unlikely]] {
HandleTLBException(regs, regs.pc); HandleTLBException(regs, regs.pc);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, false); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.pc);
return 1; return 1;
} }
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, regs.pc, paddr)) { if(!MapVAddr(regs, LOAD, regs.pc, paddr)) {
HandleTLBException(regs, regs.pc); HandleTLBException(regs, regs.pc);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.pc);
return 1; return 1;
} }
u32 instruction = mem.Read32(regs, paddr); u32 instruction = mem.Read32(regs, paddr);
if(ShouldServiceInterrupt()) { if(ShouldServiceInterrupt()) {
FireException(regs, ExceptionCode::Interrupt, 0, false); FireException(regs, ExceptionCode::Interrupt, 0, regs.pc);
return 1; return 1;
} }

View File

@@ -18,8 +18,8 @@ void JIT::special(u32 instr) {
case 0x07: srav(instr); break; case 0x07: srav(instr); break;
case 0x08: jr(instr); break; case 0x08: jr(instr); break;
case 0x09: jalr(instr); break; case 0x09: jalr(instr); break;
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, true); break; case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, true); break; case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
case 0x0F: break; // SYNC case 0x0F: break; // SYNC
case 0x10: mfhi(instr); break; case 0x10: mfhi(instr); break;
case 0x11: mthi(instr); break; case 0x11: mthi(instr); break;
@@ -116,7 +116,7 @@ void JIT::regimm(u32 instr) {
void JIT::cop2Decode(u32 instr) { void JIT::cop2Decode(u32 instr) {
if(!regs.cop0.status.cu2) { if(!regs.cop0.status.cu2) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
return; return;
} }
switch(RS(instr)) { switch(RS(instr)) {
@@ -127,7 +127,7 @@ void JIT::cop2Decode(u32 instr) {
case 0x05: dmtc2(instr); break; case 0x05: dmtc2(instr); break;
case 0x06: ctc2(instr); break; case 0x06: ctc2(instr); break;
default: default:
FireException(regs, ExceptionCode::ReservedInstruction, 2, true); FireException(regs, ExceptionCode::ReservedInstruction, 2, regs.oldPC);
} }
} }
@@ -190,7 +190,7 @@ void JIT::Emit(u32 instr) {
case 0x19: daddiu(instr); break; case 0x19: daddiu(instr); break;
case 0x1A: ldl(instr); break; case 0x1A: ldl(instr); break;
case 0x1B: ldr(instr); break; case 0x1B: ldr(instr); break;
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
case 0x20: lb(instr); break; case 0x20: lb(instr); break;
case 0x21: lh(instr); break; case 0x21: lh(instr); break;
case 0x22: lwl(instr); break; case 0x22: lwl(instr); break;

View File

@@ -291,14 +291,14 @@ void JIT::lh(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b1) > 0) { if ((address & 0b1) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr); regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr);
} }
@@ -309,14 +309,14 @@ void JIT::lw(u32 instr) {
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 physical = 0; u32 physical = 0;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical); regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical);
} }
@@ -327,10 +327,10 @@ void JIT::ll(u32 instr) {
u32 physical; u32 physical;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
if ((address & 0b11) > 0) { if ((address & 0b11) > 0) {
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} else { } else {
regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical); regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical);
@@ -346,7 +346,7 @@ void JIT::lwl(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 0) & 3); u32 shift = 8 * ((address ^ 0) & 3);
u32 mask = 0xFFFFFFFF << shift; u32 mask = 0xFFFFFFFF << shift;
@@ -361,7 +361,7 @@ void JIT::lwr(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 3) & 3); u32 shift = 8 * ((address ^ 3) & 3);
u32 mask = 0xFFFFFFFF >> shift; u32 mask = 0xFFFFFFFF >> shift;
@@ -375,14 +375,14 @@ void JIT::ld(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s64 value = mem.Read64(regs, paddr); s64 value = mem.Read64(regs, paddr);
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
@@ -391,7 +391,7 @@ void JIT::ld(u32 instr) {
void JIT::lld(u32 instr) { void JIT::lld(u32 instr) {
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC);
return; return;
} }
@@ -399,10 +399,10 @@ void JIT::lld(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
if ((address & 0b111) > 0) { if ((address & 0b111) > 0) {
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
} else { } else {
regs.gpr[RT(instr)] = mem.Read64(regs, paddr); regs.gpr[RT(instr)] = mem.Read64(regs, paddr);
regs.cop0.llbit = true; regs.cop0.llbit = true;
@@ -416,7 +416,7 @@ void JIT::ldl(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 0) & 7); s32 shift = 8 * ((address ^ 0) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
@@ -431,7 +431,7 @@ void JIT::ldr(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 7) & 7); s32 shift = 8 * ((address ^ 7) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
@@ -446,7 +446,7 @@ void JIT::lbu(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u8 value = mem.Read8(regs, paddr); u8 value = mem.Read8(regs, paddr);
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
@@ -457,13 +457,13 @@ void JIT::lhu(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b1) > 0) { if ((address & 0b1) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u16 value = mem.Read16(regs, paddr); u16 value = mem.Read16(regs, paddr);
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
@@ -474,14 +474,14 @@ void JIT::lwu(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b11) > 0) { if ((address & 0b11) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 value = mem.Read32(regs, paddr); u32 value = mem.Read32(regs, paddr);
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
@@ -493,7 +493,7 @@ void JIT::sb(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write8(regs, paddr, regs.gpr[RT(instr)]); mem.Write8(regs, paddr, regs.gpr[RT(instr)]);
} }
@@ -503,7 +503,7 @@ void JIT::sc(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b11) > 0) { if ((address & 0b11) > 0) {
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
@@ -512,7 +512,7 @@ void JIT::sc(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, STORE, address, paddr)) { if(!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, paddr, regs.gpr[RT(instr)]); mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
regs.gpr[RT(instr)] = 1; regs.gpr[RT(instr)] = 1;
@@ -524,14 +524,14 @@ void JIT::sc(u32 instr) {
void JIT::scd(u32 instr) { void JIT::scd(u32 instr) {
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC);
return; return;
} }
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b111) > 0) { if ((address & 0b111) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
@@ -540,7 +540,7 @@ void JIT::scd(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, STORE, address, paddr)) { if(!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, paddr, regs.gpr[RT(instr)]); mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
regs.gpr[RT(instr)] = 1; regs.gpr[RT(instr)] = 1;
@@ -556,7 +556,7 @@ void JIT::sh(u32 instr) {
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) { if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write16(regs, physical, regs.gpr[RT(instr)]); mem.Write16(regs, physical, regs.gpr[RT(instr)]);
} }
@@ -567,14 +567,14 @@ void JIT::sw(u32 instr) {
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) { if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, physical, regs.gpr[RT(instr)]); mem.Write32(regs, physical, regs.gpr[RT(instr)]);
} }
@@ -584,14 +584,14 @@ void JIT::sd(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) { if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write64(regs, physical, regs.gpr[RT(instr)]); mem.Write64(regs, physical, regs.gpr[RT(instr)]);
} }
@@ -602,7 +602,7 @@ void JIT::sdl(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 0) & 7); s32 shift = 8 * ((address ^ 0) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
@@ -617,7 +617,7 @@ void JIT::sdr(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 7) & 7); s32 shift = 8 * ((address ^ 7) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
@@ -632,7 +632,7 @@ void JIT::swl(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 0) & 3); u32 shift = 8 * ((address ^ 0) & 3);
u32 mask = 0xFFFFFFFF >> shift; u32 mask = 0xFFFFFFFF >> shift;
@@ -647,7 +647,7 @@ void JIT::swr(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 3) & 3); u32 shift = 8 * ((address ^ 3) & 3);
u32 mask = 0xFFFFFFFF << shift; u32 mask = 0xFFFFFFFF << shift;
@@ -1009,7 +1009,7 @@ void JIT::mthi(u32 instr) {
void JIT::trap(bool cond) { void JIT::trap(bool cond) {
if(cond) { if(cond) {
FireException(regs, ExceptionCode::Trap, 0, true); FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
} }
} }

View File

@@ -19,8 +19,8 @@ void Interpreter::special(u32 instr) {
case SRAV: srav(instr); break; case SRAV: srav(instr); break;
case JR: jr(instr); break; case JR: jr(instr); break;
case JALR: jalr(instr); break; case JALR: jalr(instr); break;
case SYSCALL: FireException(regs, ExceptionCode::Syscall, 0, true); break; case SYSCALL: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
case BREAK: FireException(regs, ExceptionCode::Breakpoint, 0, true); break; case BREAK: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
case SYNC: break; // SYNC case SYNC: break; // SYNC
case MFHI: mfhi(instr); break; case MFHI: mfhi(instr); break;
case MTHI: mthi(instr); break; case MTHI: mthi(instr); break;
@@ -93,7 +93,7 @@ void Interpreter::regimm(u32 instr) {
void Interpreter::cop2Decode(u32 instr) { void Interpreter::cop2Decode(u32 instr) {
if(!regs.cop0.status.cu2) { if(!regs.cop0.status.cu2) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
return; return;
} }
switch(RS(instr)) { switch(RS(instr)) {
@@ -104,7 +104,7 @@ void Interpreter::cop2Decode(u32 instr) {
case 0x05: dmtc2(instr); break; case 0x05: dmtc2(instr); break;
case 0x06: ctc2(instr); break; case 0x06: ctc2(instr); break;
default: default:
FireException(regs, ExceptionCode::ReservedInstruction, 2, true); FireException(regs, ExceptionCode::ReservedInstruction, 2, regs.oldPC);
} }
} }
@@ -142,7 +142,7 @@ void Interpreter::Exec(u32 instr) {
case DADDIU: daddiu(instr); break; case DADDIU: daddiu(instr); break;
case LDL: ldl(instr); break; case LDL: ldl(instr); break;
case LDR: ldr(instr); break; case LDR: ldr(instr); break;
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
case LB: lb(instr); break; case LB: lb(instr); break;
case LH: lh(instr); break; case LH: lh(instr); break;
case LWL: lwl(instr); break; case LWL: lwl(instr); break;

View File

@@ -9,7 +9,7 @@ void Interpreter::add(u32 instr) {
u32 rt = (s32)regs.gpr[RT(instr)]; u32 rt = (s32)regs.gpr[RT(instr)];
u32 result = rs + rt; u32 result = rs + rt;
if(check_signed_overflow(rs, rt, result)) { if(check_signed_overflow(rs, rt, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true); FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
} else { } else {
if (RD(instr) != 0) [[likely]] { if (RD(instr) != 0) [[likely]] {
regs.gpr[RD(instr)] = s32(result); regs.gpr[RD(instr)] = s32(result);
@@ -31,7 +31,7 @@ void Interpreter::addi(u32 instr) {
u32 imm = s32(s16(instr)); u32 imm = s32(s16(instr));
u32 result = rs + imm; u32 result = rs + imm;
if(check_signed_overflow(rs, imm, result)) { if(check_signed_overflow(rs, imm, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true); FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
} else { } else {
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
regs.gpr[RT(instr)] = s32(result); regs.gpr[RT(instr)] = s32(result);
@@ -53,7 +53,7 @@ void Interpreter::dadd(u32 instr) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 result = rt + rs; u64 result = rt + rs;
if(check_signed_overflow(rs, rt, result)) { if(check_signed_overflow(rs, rt, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true); FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
} else { } else {
if (RD(instr) != 0) [[likely]] { if (RD(instr) != 0) [[likely]] {
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
@@ -74,7 +74,7 @@ void Interpreter::daddi(u32 instr) {
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u64 result = imm + rs; u64 result = imm + rs;
if(check_signed_overflow(rs, imm, result)) { if(check_signed_overflow(rs, imm, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true); FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
} else { } else {
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
regs.gpr[RT(instr)] = result; regs.gpr[RT(instr)] = result;
@@ -217,7 +217,7 @@ void Interpreter::lb(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
regs.gpr[RT(instr)] = (s8) mem.Read8(regs, paddr); regs.gpr[RT(instr)] = (s8) mem.Read8(regs, paddr);
@@ -229,14 +229,14 @@ void Interpreter::lh(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b1, address)) { if (check_address_error(0b1, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
regs.gpr[RT(instr)] = (s16) mem.Read16(regs, paddr); regs.gpr[RT(instr)] = (s16) mem.Read16(regs, paddr);
@@ -249,14 +249,14 @@ void Interpreter::lw(u32 instr) {
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 physical = 0; u32 physical = 0;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
if(RT(instr) != 0) [[likely]] { if(RT(instr) != 0) [[likely]] {
regs.gpr[RT(instr)] = (s32) mem.Read32(regs, physical); regs.gpr[RT(instr)] = (s32) mem.Read32(regs, physical);
@@ -269,11 +269,11 @@ void Interpreter::ll(u32 instr) {
u32 physical; u32 physical;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s32 result = mem.Read32(regs, physical); s32 result = mem.Read32(regs, physical);
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
@@ -291,7 +291,7 @@ void Interpreter::lwl(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 0) & 3); u32 shift = 8 * ((address ^ 0) & 3);
u32 mask = 0xFFFFFFFF << shift; u32 mask = 0xFFFFFFFF << shift;
@@ -308,7 +308,7 @@ void Interpreter::lwr(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 3) & 3); u32 shift = 8 * ((address ^ 3) & 3);
u32 mask = 0xFFFFFFFF >> shift; u32 mask = 0xFFFFFFFF >> shift;
@@ -324,14 +324,14 @@ void Interpreter::ld(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s64 value = mem.Read64(regs, paddr); s64 value = mem.Read64(regs, paddr);
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
@@ -342,7 +342,7 @@ void Interpreter::ld(u32 instr) {
void Interpreter::lld(u32 instr) { void Interpreter::lld(u32 instr) {
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC);
return; return;
} }
@@ -350,10 +350,10 @@ void Interpreter::lld(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
} else { } else {
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
regs.gpr[RT(instr)] = mem.Read64(regs, paddr); regs.gpr[RT(instr)] = mem.Read64(regs, paddr);
@@ -369,7 +369,7 @@ void Interpreter::ldl(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 0) & 7); s32 shift = 8 * ((address ^ 0) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
@@ -386,7 +386,7 @@ void Interpreter::ldr(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 7) & 7); s32 shift = 8 * ((address ^ 7) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
@@ -403,7 +403,7 @@ void Interpreter::lbu(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u8 value = mem.Read8(regs, paddr); u8 value = mem.Read8(regs, paddr);
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
@@ -416,13 +416,13 @@ void Interpreter::lhu(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b1, address)) { if (check_address_error(0b1, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u16 value = mem.Read16(regs, paddr); u16 value = mem.Read16(regs, paddr);
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
@@ -435,14 +435,14 @@ void Interpreter::lwu(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return; return;
} }
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 value = mem.Read32(regs, paddr); u32 value = mem.Read32(regs, paddr);
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
@@ -456,7 +456,7 @@ void Interpreter::sb(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write8(regs, paddr, regs.gpr[RT(instr)]); mem.Write8(regs, paddr, regs.gpr[RT(instr)]);
} }
@@ -466,7 +466,7 @@ void Interpreter::sc(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
@@ -475,7 +475,7 @@ void Interpreter::sc(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, STORE, address, paddr)) { if(!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, paddr, regs.gpr[RT(instr)]); mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
@@ -491,14 +491,14 @@ void Interpreter::sc(u32 instr) {
void Interpreter::scd(u32 instr) { void Interpreter::scd(u32 instr) {
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC);
return; return;
} }
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
@@ -507,7 +507,7 @@ void Interpreter::scd(u32 instr) {
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, STORE, address, paddr)) { if(!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, paddr, regs.gpr[RT(instr)]); mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
if (RT(instr) != 0) [[likely]] { if (RT(instr) != 0) [[likely]] {
@@ -527,7 +527,7 @@ void Interpreter::sh(u32 instr) {
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) { if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write16(regs, physical, regs.gpr[RT(instr)]); mem.Write16(regs, physical, regs.gpr[RT(instr)]);
} }
@@ -538,14 +538,14 @@ void Interpreter::sw(u32 instr) {
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) { if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, physical, regs.gpr[RT(instr)]); mem.Write32(regs, physical, regs.gpr[RT(instr)]);
} }
@@ -555,14 +555,14 @@ void Interpreter::sd(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true); FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return; return;
} }
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) { if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write64(regs, physical, regs.gpr[RT(instr)]); mem.Write64(regs, physical, regs.gpr[RT(instr)]);
} }
@@ -573,7 +573,7 @@ void Interpreter::sdl(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 0) & 7); s32 shift = 8 * ((address ^ 0) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
@@ -588,7 +588,7 @@ void Interpreter::sdr(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
s32 shift = 8 * ((address ^ 7) & 7); s32 shift = 8 * ((address ^ 7) & 7);
u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
@@ -603,7 +603,7 @@ void Interpreter::swl(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 0) & 3); u32 shift = 8 * ((address ^ 0) & 3);
u32 mask = 0xFFFFFFFF >> shift; u32 mask = 0xFFFFFFFF >> shift;
@@ -618,7 +618,7 @@ void Interpreter::swr(u32 instr) {
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
u32 shift = 8 * ((address ^ 3) & 3); u32 shift = 8 * ((address ^ 3) & 3);
u32 mask = 0xFFFFFFFF << shift; u32 mask = 0xFFFFFFFF << shift;
@@ -863,7 +863,7 @@ void Interpreter::dsub(u32 instr) {
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s64 result = rs - rt; s64 result = rs - rt;
if(check_signed_underflow(rs, rt, result)) { if(check_signed_underflow(rs, rt, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true); FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
} else { } else {
if (RD(instr) != 0) [[likely]] { if (RD(instr) != 0) [[likely]] {
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
@@ -885,7 +885,7 @@ void Interpreter::sub(u32 instr) {
s32 rs = regs.gpr[RS(instr)]; s32 rs = regs.gpr[RS(instr)];
s32 result = rs - rt; s32 result = rs - rt;
if(check_signed_underflow(rs, rt, result)) { if(check_signed_underflow(rs, rt, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true); FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
} else { } else {
if (RD(instr) != 0) [[likely]] { if (RD(instr) != 0) [[likely]] {
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
@@ -956,7 +956,7 @@ void Interpreter::mthi(u32 instr) {
void Interpreter::trap(bool cond) { void Interpreter::trap(bool cond) {
if(cond) { if(cond) {
FireException(regs, ExceptionCode::Trap, 0, true); FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
} }
} }

View File

@@ -250,11 +250,10 @@ FORCE_INLINE bool Is64BitAddressing(Cop0& cp0, u64 addr) {
} }
} }
void FireException(Registers& regs, ExceptionCode code, int cop, bool useOldPC) { void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
bool old_exl = regs.cop0.status.exl; bool old_exl = regs.cop0.status.exl;
s64 pc = useOldPC ? regs.oldPC : regs.pc;
if(!old_exl) { if(!regs.cop0.status.exl) {
if(regs.prevDelaySlot) { if(regs.prevDelaySlot) {
regs.cop0.cause.branchDelay = true; regs.cop0.cause.branchDelay = true;
pc -= 4; pc -= 4;

View File

@@ -189,7 +189,7 @@ enum class ExceptionCode : u8 {
Watch = 23 Watch = 23
}; };
void FireException(Registers& regs, ExceptionCode code, int cop, bool useOldPC); void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc);
union Cop0Context { union Cop0Context {
u64 raw; u64 raw;

View File

@@ -71,7 +71,7 @@ struct JIT;
struct Registers; struct Registers;
struct Cop1 { struct Cop1 {
#define CheckFPUUsable_PreserveCause() do { if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); return; } } while(0) #define CheckFPUUsable_PreserveCause() do { if(!regs.cop0.status.cu1) { FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC); return; } } while(0)
#define CheckFPUUsable() do { CheckFPUUsable_PreserveCause(); regs.cop1.fcr31.cause = 0; } while(0) #define CheckFPUUsable() do { CheckFPUUsable_PreserveCause(); regs.cop1.fcr31.cause = 0; } while(0)
Cop1(); Cop1();
u32 fcr0{}; u32 fcr0{};

View File

@@ -9,8 +9,9 @@
namespace n64 { namespace n64 {
FORCE_INLINE bool FireFPUException(Registers& regs) { FORCE_INLINE bool FireFPUException(Registers& regs) {
FCR31& fcr31 = regs.cop1.fcr31; FCR31& fcr31 = regs.cop1.fcr31;
if(fcr31.cause & ((1 << 5) | fcr31.enable)) { u32 enable = fcr31.enable | (1 << 5);
FireException(regs, ExceptionCode::FloatingPointError, 0, true); if(fcr31.cause & enable) {
FireException(regs, ExceptionCode::FloatingPointError, 0, regs.oldPC);
return true; return true;
} }
@@ -759,7 +760,7 @@ void Cop1::lwc1Interp(Registers& regs, Mem& mem, u32 instr) {
u32 physical; u32 physical;
if(!MapVAddr(regs, LOAD, addr, physical)) { if(!MapVAddr(regs, LOAD, addr, physical)) {
HandleTLBException(regs, addr); HandleTLBException(regs, addr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 data = mem.Read32(regs, physical); u32 data = mem.Read32(regs, physical);
SetFGR_FR<u32>(regs.cop0, FT(instr), data); SetFGR_FR<u32>(regs.cop0, FT(instr), data);
@@ -772,7 +773,7 @@ void Cop1::swc1Interp(Registers& regs, Mem& mem, u32 instr) {
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, addr, physical)) { if(!MapVAddr(regs, STORE, addr, physical)) {
HandleTLBException(regs, addr); HandleTLBException(regs, addr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write32(regs, physical, GetFGR_FR<u32>(regs.cop0, FT(instr))); mem.Write32(regs, physical, GetFGR_FR<u32>(regs.cop0, FT(instr)));
} }
@@ -790,7 +791,7 @@ void Cop1::ldc1Interp(Registers& regs, Mem& mem, u32 instr) {
u32 physical; u32 physical;
if(!MapVAddr(regs, LOAD, addr, physical)) { if(!MapVAddr(regs, LOAD, addr, physical)) {
HandleTLBException(regs, addr); HandleTLBException(regs, addr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u64 data = mem.Read64(regs, physical); u64 data = mem.Read64(regs, physical);
SetFGR_FR<u64>(regs.cop0, FT(instr), data); SetFGR_FR<u64>(regs.cop0, FT(instr), data);
@@ -803,7 +804,7 @@ void Cop1::sdc1Interp(Registers& regs, Mem& mem, u32 instr) {
u32 physical; u32 physical;
if(!MapVAddr(regs, STORE, addr, physical)) { if(!MapVAddr(regs, STORE, addr, physical)) {
HandleTLBException(regs, addr); HandleTLBException(regs, addr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write64(regs, physical, GetFGR_FR<u64>(regs.cop0, FT(instr))); mem.Write64(regs, physical, GetFGR_FR<u64>(regs.cop0, FT(instr)));
} }