unaligned jump exceptions handled properly now
This commit is contained in:
@@ -7,6 +7,12 @@ int Interpreter::Step() {
|
|||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
regs.delaySlot = false;
|
regs.delaySlot = false;
|
||||||
|
|
||||||
|
if(check_address_error(0b11, u64(regs.pc))) [[unlikely]] {
|
||||||
|
HandleTLBException(regs, regs.pc);
|
||||||
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, false);
|
||||||
|
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);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ struct Interpreter : BaseCPU {
|
|||||||
private:
|
private:
|
||||||
u64 cop2Latch{};
|
u64 cop2Latch{};
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
|
#define check_address_error(mask, vaddr) (((!regs.cop0.is_64bit_addressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
||||||
|
|
||||||
[[nodiscard]] FORCE_INLINE bool ShouldServiceInterrupt() override {
|
[[nodiscard]] FORCE_INLINE bool ShouldServiceInterrupt() override {
|
||||||
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
|
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include <core/Interpreter.hpp>
|
#include <core/Interpreter.hpp>
|
||||||
|
|
||||||
#define check_address_error(mask, vaddr) (((!regs.cop0.is_64bit_addressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
|
||||||
#define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
|
#define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
|
||||||
#define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
|
#define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
|
||||||
|
|
||||||
@@ -663,14 +662,15 @@ void Interpreter::jal(u32 instr) {
|
|||||||
|
|
||||||
void Interpreter::jalr(u32 instr) {
|
void Interpreter::jalr(u32 instr) {
|
||||||
u64 addr = regs.gpr[RS(instr)];
|
u64 addr = regs.gpr[RS(instr)];
|
||||||
if(check_address_error(0b11, addr)) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
|
||||||
} else {
|
|
||||||
branch(true, addr);
|
branch(true, addr);
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
regs.gpr[RD(instr)] = regs.pc + 4;
|
regs.gpr[RD(instr)] = regs.pc + 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Interpreter::jr(u32 instr) {
|
||||||
|
u64 address = regs.gpr[RS(instr)];
|
||||||
|
branch(true, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::slti(u32 instr) {
|
void Interpreter::slti(u32 instr) {
|
||||||
@@ -858,15 +858,6 @@ void Interpreter::dsra32(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jr(u32 instr) {
|
|
||||||
s64 address = regs.gpr[RS(instr)];
|
|
||||||
if(check_address_error(0b11, address)) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
|
||||||
} else {
|
|
||||||
branch(true, address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interpreter::dsub(u32 instr) {
|
void Interpreter::dsub(u32 instr) {
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
s64 rs = regs.gpr[RS(instr)];
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
|
|||||||
Reference in New Issue
Block a user