better jit macros

This commit is contained in:
SimoneN64
2023-12-08 18:43:29 +01:00
parent aca784eb58
commit f5ed20ea99
3 changed files with 248 additions and 126 deletions

View File

@@ -35,25 +35,23 @@ Fn JIT::Recompile() {
cycles = 0;
prologue();
mov(rbp, u64(this));
mov(rdi, u64(this) + offsetof(JIT, regs));
mov(rdi, u64(this) + THIS_OFFSET(regs));
while(stable) {
cycles++;
CheckCompareInterrupt();
mov(rax, byte[rdi + offsetof(Registers, delaySlot)]);
mov(byte[rdi + offsetof(Registers, prevDelaySlot)], rax);
mov(byte[rdi + offsetof(Registers, delaySlot)], 0);
mov(rax, REG(byte, delaySlot));
mov(REG(byte, prevDelaySlot), rax);
mov(REG(byte, delaySlot), 0);
u32 paddr = 0;
if (!MapVAddr(regs, LOAD, regs.pc, paddr)) {
mov(rsi, regs.pc);
push(rax);
call(HandleTLBException);
emitCall(HandleTLBException);
mov(rsi, u64(GetTLBExceptionCode(regs.cop0.tlbError, LOAD)));
CodeGenerator::xor_(rdx, rdx);
CodeGenerator::xor_(rcx, rcx);
push(rax);
call(FireException);
emitCall(FireException);
goto _epilogue;
}
@@ -70,11 +68,11 @@ Fn JIT::Recompile() {
goto _epilogue;
}
mov(rax, qword[rdi + offsetof(Registers, pc)]);
mov(qword[rdi + offsetof(Registers, oldPC)], rax);
mov(rax, qword[rdi + offsetof(Registers, nextPC)]);
mov(qword[rdi + offsetof(Registers, pc)], rax);
CodeGenerator::add(qword[rdi + offsetof(Registers, nextPC)], 4);
mov(rax, REG(qword, pc));
mov(REG(qword, oldPC), rax);
mov(rax, REG(qword, nextPC));
mov(REG(qword, pc), rax);
CodeGenerator::add(REG(qword, nextPC), 4);
}
_epilogue:
epilogue();

View File

@@ -7,8 +7,11 @@
namespace n64 {
using Fn = int(*)();
#define GPR(x) qword[rdi + offsetof(Registers, gpr[(x)])]
#define REG(ptr, member) ptr[rdi + offsetof(Registers, member)]
#define THIS_OFFSET(x) ((uintptr_t)(&x) - (uintptr_t)this)
#define GPR_OFFSET(x) ((uintptr_t)&regs.gpr[(x)] - (uintptr_t)this)
#define REG_OFFSET(member) ((uintptr_t)&regs.member - (uintptr_t)this)
#define GPR(ptr, x) ptr[rdi + GPR_OFFSET(x)]
#define REG(ptr, member) ptr[rdi + REG_OFFSET(member)]
// 4KiB aligned pages
#define BLOCKCACHE_OUTER_SHIFT 12
#define BLOCKCACHE_PAGE_SIZE (1 << BLOCKCACHE_OUTER_SHIFT)
@@ -33,7 +36,7 @@ private:
template<class T>
void emitMemberCall(T func, void* thisObj) {
void* funcPtr;
T* funcPtr;
auto thisPtr = reinterpret_cast<uintptr_t>(thisObj);
#ifdef ABI_WINDOWS
static_assert(sizeof(T) == 8, "[JIT]: Invalid size for member function pointer");
@@ -58,6 +61,24 @@ private:
pop(rdi);
}
template<class T>
void emitCall(T func) {
T* funcPtr;
#ifdef ABI_WINDOWS
std::memcpy(&funcPtr, &func, sizeof(T));
#elif defined(ABI_UNIX)
uintptr_t tmpArr[2];
std::memcpy(tmpArr, &func, sizeof(T));
funcPtr = reinterpret_cast<void*>(tmpArr[0]);
#else
Util::panic("Huh?!");
#endif
push(rdi);
call(funcPtr);
pop(rdi);
}
bool isStable(u32 instr) {
u8 mask = (instr >> 26) & 0x3f;
switch(mask) {
@@ -99,13 +120,8 @@ private:
ret();
}
static u8 codecache[1 << 25] __attribute__((aligned(4096)));
Fn* blocks[BLOCKCACHE_OUTER_SIZE]{};
u8 Read8(u64 addr) {
return mem.Read<u8>(regs, addr);
}
std::vector<u8> Serialize() override { return {}; }
void Deserialize(const std::vector<u8>&) override { }

View File

@@ -7,10 +7,10 @@
namespace n64 {
void JIT::add(u32 instr) {
if (RD(instr) != 0) [[likely]] {
movsx(eax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // rs
movsx(ecx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // rt
movsx(eax, GPR(dword, RS(instr))); // rs
movsx(ecx, GPR(dword, RT(instr))); // rt
CodeGenerator::add(eax, ecx);
mov(dword[rdi + offsetof(Registers, gpr[RD(instr)])], eax); // rd
mov(GPR(dword, RD(instr)), eax); // rd
}
}
@@ -20,10 +20,10 @@ void JIT::addu(u32 instr) {
void JIT::addi(u32 instr) {
if (RT(instr) != 0) [[likely]] {
movsx(eax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]);
movsx(eax, GPR(dword, RS(instr)));
mov(ecx, s32(s16(instr)));
CodeGenerator::add(eax, ecx);
mov(dword[rdi + offsetof(Registers, gpr[RT(instr)])], eax);
mov(GPR(dword, RT(instr)), eax);
}
}
@@ -33,23 +33,87 @@ void JIT::addiu(u32 instr) {
void JIT::dadd(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RS(instr))); // rs
mov(rcx, GPR(RT(instr))); // rt
mov(rax, GPR(qword, RS(instr))); // rs
mov(rcx, GPR(qword, RT(instr))); // rt
CodeGenerator::add(rax, rcx);
mov(GPR(RD(instr)), rax); // rd
mov(GPR(qword, RD(instr)), rax); // rd
}
}
void JIT::bltz(u32) {
}
void JIT::bgez(u32) {
}
void JIT::bltzl(u32) {
}
void JIT::bgezl(u32) {
}
void JIT::bltzal(u32) {
}
void JIT::bgezal(u32) {
}
void JIT::bltzall(u32) {
}
void JIT::bgezall(u32) {
}
void JIT::beq(u32) {
}
void JIT::bne(u32) {
}
void JIT::blez(u32) {
}
void JIT::bgtz(u32) {
}
void JIT::beql(u32) {
}
void JIT::bnel(u32) {
}
void JIT::blezl(u32) {
}
void JIT::bgtzl(u32) {
}
void JIT::daddu(u32 instr) {
dadd(instr);
}
void JIT::daddi(u32 instr) {
if (RT(instr) != 0) [[likely]] {
mov(rax, GPR(RS(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, s64(s16(instr)));
CodeGenerator::add(rax, rcx);
mov(GPR(RT(instr)), rax);
mov(GPR(qword, RT(instr)), rax);
}
}
@@ -58,8 +122,8 @@ void JIT::daddiu(u32 instr) {
}
void JIT::div(u32 instr) {
movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend
movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // divisor
movsxd(rax, GPR(dword, RS(instr))); // dividend
movsxd(rcx, GPR(dword, RT(instr))); // divisor
cmp(rcx, 0);
je("div_divisor==0");
@@ -80,8 +144,8 @@ void JIT::div(u32 instr) {
}
void JIT::divu(u32 instr) {
movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend
movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // divisor
movsxd(rax, GPR(dword, RS(instr))); // dividend
movsxd(rcx, GPR(dword, RT(instr))); // divisor
cmp(rcx, 0);
je("divu_divisor==0");
@@ -98,8 +162,8 @@ void JIT::divu(u32 instr) {
}
void JIT::ddiv(u32 instr) {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, GPR(qword, RT(instr)));
mov(r8, 0x8000000000000000);
mov(r9, rax);
CodeGenerator::xor_(r9, r8);
@@ -129,8 +193,8 @@ void JIT::ddiv(u32 instr) {
}
void JIT::ddivu(u32 instr) {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, GPR(qword, RT(instr)));
cmp(rcx, 0);
je("ddivu_divisor==0");
CodeGenerator::div(rcx);
@@ -146,40 +210,36 @@ void JIT::ddivu(u32 instr) {
void JIT::lui(u32 instr) {
u64 val = s64(s16(instr));
val <<= 16;
mov(GPR(RT(instr)), val);
mov(GPR(qword, RT(instr)), val);
}
void JIT::lb(u32 instr) {
mov(rdx, GPR(RS(instr)));
mov(rdx, GPR(qword, RS(instr)));
CodeGenerator::add(rdx, s64(s16(instr)));
mov(rsi, LOAD);
push(rcx);
lea(rcx, dword[rbp-4]);
call(MapVAddr);
emitCall(MapVAddr);
pop(rcx);
cmp(rax, 0);
je("lb_exception");
mov(rsi, dword[rbp-4]);
push(rcx);
emitMemberCall(&JIT::Read8, this);
emitMemberCall(&Mem::Read<u8>, &mem);
pop(rcx);
mov(GPR(RT(instr)), rax.cvt8());
mov(GPR(qword, RT(instr)), rax.cvt8());
L("lb_exception");
mov(rsi, rdx);
push(rax);
call(HandleTLBException);
pop(rax);
emitCall(HandleTLBException);
push(rsi);
mov(rdi, REG(byte, cop0.tlbError));
mov(rsi, LOAD);
call(GetTLBExceptionCode);
emitCall(GetTLBExceptionCode);
pop(rsi);
mov(rsi, rax);
mov(rdx, 0);
mov(rcx, 1);
push(rax);
call(FireException);
pop(rax);
emitCall(FireException);
}
void JIT::lh(u32 instr) {
@@ -554,27 +614,27 @@ void JIT::swr(u32 instr) {
void JIT::ori(u32 instr) {
s64 imm = (u16)instr;
mov(rax, GPR(RS(instr)));
mov(rax, GPR(qword, RS(instr)));
CodeGenerator::or_(rax, imm);
mov(GPR(RT(instr)), rax);
mov(GPR(qword, RT(instr)), rax);
}
void JIT::or_(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, GPR(qword, RT(instr)));
CodeGenerator::or_(rax, rcx);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::nor(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, GPR(qword, RT(instr)));
CodeGenerator::or_(rax, rcx);
not_(rax);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
@@ -588,247 +648,295 @@ void JIT::j(u32 instr) {
void JIT::jal(u32 instr) {
mov(rax, qword[rdi + offsetof(Registers, nextPC)]);
mov(GPR(31), rax);
mov(GPR(qword, 31), rax);
j(instr);
}
void JIT::jalr(u32 instr) {
mov(byte[rdi + offsetof(Registers, delaySlot)], 1);
mov(rax, GPR(RS(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(qword[rdi + offsetof(Registers, nextPC)], rax);
if (RD(instr) != 0) [[likely]] {
mov(rax, qword[rdi + offsetof(Registers, pc)]);
CodeGenerator::add(rax, 4);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::slti(u32 instr) {
mov(rax, s64(s16(instr)));
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
cmp(rcx, rax);
setl(GPR(RT(instr)));
setl(GPR(qword, RT(instr)));
}
void JIT::sltiu(u32 instr) {
mov(rax, s64(s16(instr)));
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
cmp(rcx, rax);
setb(GPR(RT(instr)));
setb(GPR(qword, RT(instr)));
}
void JIT::slt(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, GPR(qword, RT(instr)));
cmp(rax, rcx);
setl(GPR(RD(instr)));
setl(GPR(qword, RD(instr)));
}
}
void JIT::sltu(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(rcx, GPR(qword, RT(instr)));
cmp(rax, rcx);
setb(GPR(RD(instr)));
setb(GPR(qword, RD(instr)));
}
}
void JIT::xori(u32 instr) {
s64 imm = (u16)instr;
mov(rax, (u16)instr);
mov(rcx, GPR(RS(instr)));
mov(rax, imm);
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::xor_(rcx, rax);
mov(GPR(RT(instr)), rcx);
mov(GPR(qword, RT(instr)), rcx);
}
void JIT::xor_(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RT(instr)));
mov(rcx, GPR(RS(instr)));
mov(rax, GPR(qword, RT(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::xor_(rax, rcx);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::andi(u32 instr) {
s64 imm = (u16)instr;
mov(rax, (u16)instr);
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(rcx, rax);
mov(GPR(RT(instr)), rcx);
mov(GPR(qword, RT(instr)), rcx);
}
void JIT::and_(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RT(instr)));
mov(rcx, GPR(RS(instr)));
mov(rax, GPR(qword, RT(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(rax, rcx);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::sll(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sal(rax, sa);
movsxd(rcx, eax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
void JIT::sllv(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(cl, 0x1F);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sal(rax, cl);
movsxd(rcx, eax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
void JIT::dsll32(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f) + 32;
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sal(rax, sa);
mov(GPR(RT(instr)), rax);
mov(GPR(qword, RT(instr)), rax);
}
}
void JIT::dsll(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sal(rax, sa);
mov(GPR(RT(instr)), rax);
mov(GPR(qword, RT(instr)), rax);
}
}
void JIT::dsllv(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(cl, 63);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sal(rax, cl);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::srl(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
CodeGenerator::shr(rax, sa);
movsxd(rcx, eax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
void JIT::srlv(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(cl, 0x1F);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
shr(rax, cl);
movsxd(rcx, eax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
void JIT::tgei(u32) {
}
void JIT::tgeiu(u32) {
}
void JIT::tlti(u32) {
}
void JIT::tltiu(u32) {
}
void JIT::teqi(u32) {
}
void JIT::tnei(u32) {
}
void JIT::tge(u32) {
}
void JIT::tgeu(u32) {
}
void JIT::tlt(u32) {
}
void JIT::tltu(u32) {
}
void JIT::teq(u32) {
}
void JIT::tne(u32) {
}
void JIT::dsrl(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
CodeGenerator::shr(rax, sa);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::dsrlv(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(cl, 63);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
shr(rax, cl);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::dsrl32(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f) + 32;
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
CodeGenerator::shr(rax, sa);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::sra(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sar(rax, sa);
movsxd(rcx, eax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
void JIT::srav(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(cl, 0x1F);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sar(rax, cl);
movsxd(rcx, eax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
void JIT::dsra(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sar(rax, sa);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::dsrav(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rcx, GPR(RS(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::and_(cl, 63);
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sar(rax, cl);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::dsra32(u32 instr) {
if (RD(instr) != 0) [[likely]] {
u8 sa = ((instr >> 6) & 0x1f) + 32;
mov(rax, GPR(RT(instr)));
mov(rax, GPR(qword, RT(instr)));
sar(rax, sa);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}
void JIT::jr(u32 instr) {
mov(rax, GPR(RS(instr)));
mov(rax, GPR(qword, RS(instr)));
mov(REG(byte, delaySlot), 1);
mov(REG(qword, nextPC), rax);
}
void JIT::dsub(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(rax, GPR(RT(instr)));
mov(rcx, GPR(RS(instr)));
mov(rax, GPR(qword, RT(instr)));
mov(rcx, GPR(qword, RS(instr)));
CodeGenerator::sub(rcx, rax);
mov(GPR(RD(instr)), rcx);
mov(GPR(qword, RD(instr)), rcx);
}
}
@@ -838,11 +946,11 @@ void JIT::dsubu(u32 instr) {
void JIT::sub(u32 instr) {
if (RD(instr) != 0) [[likely]] {
mov(eax, GPR(RT(instr)));
mov(ecx, GPR(RS(instr)));
mov(eax, GPR(qword, RT(instr)));
mov(ecx, GPR(qword, RS(instr)));
CodeGenerator::sub(ecx, eax);
movsxd(rax, ecx);
mov(GPR(RD(instr)), rax);
mov(GPR(qword, RD(instr)), rax);
}
}