JIT: Passing first 2 tests in basic_simpleboot

This commit is contained in:
SimoneN64
2023-03-20 23:37:54 +01:00
parent 0f2a999f00
commit 94ce40429f
15 changed files with 319 additions and 289 deletions

View File

@@ -1,7 +1,6 @@
#include <core/JIT.hpp>
#define se_imm(x) ((s16)((x) & 0xFFFF))
#define check_address_error(mask, addr) (((!regs.cop0.is_64bit_addressing) && (s32)(addr) != (addr)) || (((addr) & (mask)) != 0))
#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_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
@@ -11,6 +10,9 @@ void add(JIT& dyn, u32 instr) {
u32 rs = (s32)regs.gpr[RS(instr)];
u32 rt = (s32)regs.gpr[RT(instr)];
u32 result = rs + rt;
Util::debug("add r{}, r{}, r{} = {:08X}\n", RD(instr), RS(instr), RT(instr), result);
if(check_signed_overflow(rs, rt, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true);
} else {
@@ -27,6 +29,7 @@ void addu(JIT& dyn, u32 instr) {
s32 rt = (s32)regs.gpr[RT(instr)];
s32 result = rs + rt;
regs.gpr[RD(instr)] = result;
Util::debug("addu r{}, r{}, r{} = {:08X}\n", RD(instr), RS(instr), RT(instr), (u32)result);
}
}
@@ -35,6 +38,7 @@ void addi(JIT& dyn, u32 instr) {
u32 rs = regs.gpr[RS(instr)];
u32 imm = s32(s16(instr));
u32 result = rs + imm;
Util::debug("addi r{}, r{}, {:08X} = {:08X}\n", RT(instr), RS(instr), imm, result);
if(check_signed_overflow(rs, imm, result)) {
FireException(regs, ExceptionCode::Overflow, 0, true);
} else {
@@ -174,8 +178,8 @@ void branch(JIT& dyn, bool cond, s64 address) {
void branch_likely(JIT& dyn, bool cond, s64 address) {
Registers& regs = dyn.regs;
regs.delaySlot = true;
if (cond) {
regs.delaySlot = true;
regs.nextPC = address;
} else {
regs.SetPC64(regs.nextPC);
@@ -184,7 +188,8 @@ void branch_likely(JIT& dyn, bool cond, s64 address) {
void b(JIT& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
s64 offset = (s64)se_imm(instr) << 2;
s16 imm = instr;
s64 offset = (s64)imm << 2;
s64 address = regs.pc + offset;
branch(dyn, cond, address);
}
@@ -192,14 +197,16 @@ void b(JIT& dyn, u32 instr, bool cond) {
void blink(JIT& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
regs.gpr[31] = regs.nextPC;
s64 offset = (s64)se_imm(instr) << 2;
s16 imm = instr;
s64 offset = (s64)imm << 2;
s64 address = regs.pc + offset;
branch(dyn, cond, address);
}
void bl(JIT& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
s64 offset = (s64)se_imm(instr) << 2;
s16 imm = instr;
s64 offset = (s64)imm << 2;
s64 address = regs.pc + offset;
branch_likely(dyn, cond, address);
}
@@ -207,7 +214,8 @@ void bl(JIT& dyn, u32 instr, bool cond) {
void bllink(JIT& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
regs.gpr[31] = regs.nextPC;
s64 offset = (s64)se_imm(instr) << 2;
s16 imm = instr;
s64 offset = (s64)imm << 2;
s64 address = regs.pc + offset;
branch_likely(dyn, cond, address);
}
@@ -247,7 +255,7 @@ void lh(JIT& dyn, u32 instr) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
} else {
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address);
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr);
}
}
@@ -256,7 +264,7 @@ void lw(JIT& dyn, u32 instr) {
Mem& mem = dyn.mem;
s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(address, 0b11)) {
if (check_address_error(0b11, address)) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
return;
@@ -330,14 +338,20 @@ void ld(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b111)) {
if (check_address_error(0b111, address)) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
return;
}
s64 value = mem.Read64(regs, address);
regs.gpr[RT(instr)] = value;
u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
} else {
s64 value = mem.Read64(regs, paddr);
regs.gpr[RT(instr)] = value;
}
}
void lld(JIT& dyn, u32 instr) {
@@ -402,43 +416,66 @@ void lbu(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr;
u8 value = mem.Read8(regs, address);
regs.gpr[RT(instr)] = value;
u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
} else {
u8 value = mem.Read8(regs, paddr);
regs.gpr[RT(instr)] = value;
}
}
void lhu(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) {
if ((address & 0b1) > 0) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
return;
}
u16 value = mem.Read16(regs, address);
regs.gpr[RT(instr)] = value;
u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
} else {
u16 value = mem.Read16(regs, paddr);
regs.gpr[RT(instr)] = value;
}
}
void lwu(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) {
if ((address & 0b11) > 0) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
return;
}
u32 value = mem.Read32(regs, address);
regs.gpr[RT(instr)] = value;
u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
} else {
u32 value = mem.Read32(regs, paddr);
regs.gpr[RT(instr)] = value;
}
}
void sb(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u32 address = regs.gpr[RS(instr)] + (s16)instr;
mem.Write8(regs, dyn, address, regs.gpr[RT(instr)]);
u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
} else {
mem.Write8(regs, paddr, regs.gpr[RT(instr)]);
}
}
void sc(JIT& dyn, u32 instr) {
@@ -458,7 +495,7 @@ void sc(JIT& dyn, u32 instr) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
} else {
mem.Write32(regs, dyn, paddr, regs.gpr[RT(instr)]);
mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
regs.gpr[RT(instr)] = 1;
}
} else {
@@ -469,37 +506,44 @@ void sc(JIT& dyn, u32 instr) {
void scd(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
return;
}
s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b111)) {
if ((address & 0b111) > 0) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
return;
}
if(regs.cop0.llbit) {
mem.Write64(regs, dyn, address, regs.gpr[RT(instr)]);
regs.cop0.llbit = false;
u32 paddr = 0;
if(!MapVAddr(regs, STORE, address, paddr)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
} else {
mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
regs.gpr[RT(instr)] = 1;
}
} else {
regs.gpr[RT(instr)] = 0;
}
regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit);
regs.cop0.llbit = false;
}
void sh(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
return;
}
u32 physical;
if(!MapVAddr(regs, STORE, address, physical)) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
} else {
mem.Write16(regs, dyn, physical, regs.gpr[RT(instr)]);
mem.Write16(regs, physical, regs.gpr[RT(instr)]);
}
}
@@ -508,7 +552,7 @@ void sw(JIT& dyn, u32 instr) {
Mem& mem = dyn.mem;
s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(address, 0b11)) {
if (check_address_error(0b11, address)) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
return;
@@ -519,7 +563,7 @@ void sw(JIT& dyn, u32 instr) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
} else {
mem.Write32(regs, dyn, physical, regs.gpr[RT(instr)]);
mem.Write32(regs, physical, regs.gpr[RT(instr)]);
}
}
@@ -527,7 +571,7 @@ void sd(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) {
if (check_address_error(0b111, address)) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
return;
@@ -538,9 +582,8 @@ void sd(JIT& dyn, u32 instr) {
HandleTLBException(regs, address);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
} else {
mem.Write64(regs, dyn, physical, regs.gpr[RT(instr)]);
mem.Write64(regs, physical, regs.gpr[RT(instr)]);
}
}
void sdl(JIT& dyn, u32 instr) {
@@ -556,7 +599,7 @@ void sdl(JIT& dyn, u32 instr) {
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
u64 data = mem.Read64(regs, paddr & ~7);
u64 rt = regs.gpr[RT(instr)];
mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt >> shift));
mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift));
}
}
@@ -573,7 +616,7 @@ void sdr(JIT& dyn, u32 instr) {
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
u64 data = mem.Read64(regs, paddr & ~7);
u64 rt = regs.gpr[RT(instr)];
mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt << shift));
mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift));
}
}
@@ -590,7 +633,7 @@ void swl(JIT& dyn, u32 instr) {
u32 mask = 0xFFFFFFFF >> shift;
u32 data = mem.Read32(regs, paddr & ~3);
u32 rt = regs.gpr[RT(instr)];
mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt >> shift));
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift));
}
}
@@ -607,7 +650,7 @@ void swr(JIT& dyn, u32 instr) {
u32 mask = 0xFFFFFFFF << shift;
u32 data = mem.Read32(regs, paddr & ~3);
u32 rt = regs.gpr[RT(instr)];
mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt << shift));
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift));
}
}
@@ -634,8 +677,9 @@ void nor(JIT& dyn, u32 instr) {
void j(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
u64 target = (instr & 0x3ffffff) << 2;
u64 address = ((regs.pc - 4) & ~0xfffffff) | target;
Mem& mem = dyn.mem;
s32 target = (instr & 0x3ffffff) << 2;
s64 address = (regs.oldPC & ~0xfffffff) | target;
branch(dyn, true, address);
}
@@ -648,6 +692,7 @@ void jal(JIT& dyn, u32 instr) {
void jalr(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
branch(dyn, true, regs.gpr[RS(instr)]);
if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.pc + 4;
@@ -656,12 +701,14 @@ void jalr(JIT& dyn, u32 instr) {
void slti(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr);
s16 imm = instr;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < imm;
}
void sltiu(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr);
s16 imm = instr;
regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < imm;
}
void slt(JIT& dyn, u32 instr) {
@@ -812,8 +859,8 @@ void sra(JIT& dyn, u32 instr) {
void srav(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 rt = regs.gpr[RT(instr)];
if(likely(RD(instr) != 0)) {
s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)];
u8 sa = rs & 0x1f;
s32 result = rt >> sa;
@@ -855,11 +902,6 @@ void dsra32(JIT& dyn, u32 instr) {
void jr(JIT& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 address = regs.gpr[RS(instr)];
if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address);
FireException(regs, ExceptionCode::DataBusError, 0, true);
}
branch(dyn, true, address);
}
@@ -972,9 +1014,8 @@ void mthi(JIT& dyn, u32 instr) {
}
void trap(JIT& dyn, bool cond) {
Registers& regs = dyn.regs;
if(cond) {
FireException(regs, ExceptionCode::Trap, 0, true);
FireException(dyn.regs, ExceptionCode::Trap, 0, true);
}
}