better jit macros
This commit is contained in:
@@ -35,25 +35,23 @@ Fn JIT::Recompile() {
|
|||||||
cycles = 0;
|
cycles = 0;
|
||||||
prologue();
|
prologue();
|
||||||
mov(rbp, u64(this));
|
mov(rbp, u64(this));
|
||||||
mov(rdi, u64(this) + offsetof(JIT, regs));
|
mov(rdi, u64(this) + THIS_OFFSET(regs));
|
||||||
while(stable) {
|
while(stable) {
|
||||||
cycles++;
|
cycles++;
|
||||||
CheckCompareInterrupt();
|
CheckCompareInterrupt();
|
||||||
|
|
||||||
mov(rax, byte[rdi + offsetof(Registers, delaySlot)]);
|
mov(rax, REG(byte, delaySlot));
|
||||||
mov(byte[rdi + offsetof(Registers, prevDelaySlot)], rax);
|
mov(REG(byte, prevDelaySlot), rax);
|
||||||
mov(byte[rdi + offsetof(Registers, delaySlot)], 0);
|
mov(REG(byte, delaySlot), 0);
|
||||||
|
|
||||||
u32 paddr = 0;
|
u32 paddr = 0;
|
||||||
if (!MapVAddr(regs, LOAD, regs.pc, paddr)) {
|
if (!MapVAddr(regs, LOAD, regs.pc, paddr)) {
|
||||||
mov(rsi, regs.pc);
|
mov(rsi, regs.pc);
|
||||||
push(rax);
|
emitCall(HandleTLBException);
|
||||||
call(HandleTLBException);
|
|
||||||
mov(rsi, u64(GetTLBExceptionCode(regs.cop0.tlbError, LOAD)));
|
mov(rsi, u64(GetTLBExceptionCode(regs.cop0.tlbError, LOAD)));
|
||||||
CodeGenerator::xor_(rdx, rdx);
|
CodeGenerator::xor_(rdx, rdx);
|
||||||
CodeGenerator::xor_(rcx, rcx);
|
CodeGenerator::xor_(rcx, rcx);
|
||||||
push(rax);
|
emitCall(FireException);
|
||||||
call(FireException);
|
|
||||||
goto _epilogue;
|
goto _epilogue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,11 +68,11 @@ Fn JIT::Recompile() {
|
|||||||
goto _epilogue;
|
goto _epilogue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mov(rax, qword[rdi + offsetof(Registers, pc)]);
|
mov(rax, REG(qword, pc));
|
||||||
mov(qword[rdi + offsetof(Registers, oldPC)], rax);
|
mov(REG(qword, oldPC), rax);
|
||||||
mov(rax, qword[rdi + offsetof(Registers, nextPC)]);
|
mov(rax, REG(qword, nextPC));
|
||||||
mov(qword[rdi + offsetof(Registers, pc)], rax);
|
mov(REG(qword, pc), rax);
|
||||||
CodeGenerator::add(qword[rdi + offsetof(Registers, nextPC)], 4);
|
CodeGenerator::add(REG(qword, nextPC), 4);
|
||||||
}
|
}
|
||||||
_epilogue:
|
_epilogue:
|
||||||
epilogue();
|
epilogue();
|
||||||
|
|||||||
@@ -7,8 +7,11 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
using Fn = int(*)();
|
using Fn = int(*)();
|
||||||
#define GPR(x) qword[rdi + offsetof(Registers, gpr[(x)])]
|
#define THIS_OFFSET(x) ((uintptr_t)(&x) - (uintptr_t)this)
|
||||||
#define REG(ptr, member) ptr[rdi + offsetof(Registers, member)]
|
#define GPR_OFFSET(x) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)this)
|
||||||
|
#define REG_OFFSET(member) ((uintptr_t)®s.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
|
// 4KiB aligned pages
|
||||||
#define BLOCKCACHE_OUTER_SHIFT 12
|
#define BLOCKCACHE_OUTER_SHIFT 12
|
||||||
#define BLOCKCACHE_PAGE_SIZE (1 << BLOCKCACHE_OUTER_SHIFT)
|
#define BLOCKCACHE_PAGE_SIZE (1 << BLOCKCACHE_OUTER_SHIFT)
|
||||||
@@ -33,7 +36,7 @@ private:
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void emitMemberCall(T func, void* thisObj) {
|
void emitMemberCall(T func, void* thisObj) {
|
||||||
void* funcPtr;
|
T* funcPtr;
|
||||||
auto thisPtr = reinterpret_cast<uintptr_t>(thisObj);
|
auto thisPtr = reinterpret_cast<uintptr_t>(thisObj);
|
||||||
#ifdef ABI_WINDOWS
|
#ifdef ABI_WINDOWS
|
||||||
static_assert(sizeof(T) == 8, "[JIT]: Invalid size for member function pointer");
|
static_assert(sizeof(T) == 8, "[JIT]: Invalid size for member function pointer");
|
||||||
@@ -58,6 +61,24 @@ private:
|
|||||||
pop(rdi);
|
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) {
|
bool isStable(u32 instr) {
|
||||||
u8 mask = (instr >> 26) & 0x3f;
|
u8 mask = (instr >> 26) & 0x3f;
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
@@ -99,13 +120,8 @@ private:
|
|||||||
ret();
|
ret();
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 codecache[1 << 25] __attribute__((aligned(4096)));
|
|
||||||
Fn* blocks[BLOCKCACHE_OUTER_SIZE]{};
|
Fn* blocks[BLOCKCACHE_OUTER_SIZE]{};
|
||||||
|
|
||||||
u8 Read8(u64 addr) {
|
|
||||||
return mem.Read<u8>(regs, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> Serialize() override { return {}; }
|
std::vector<u8> Serialize() override { return {}; }
|
||||||
void Deserialize(const std::vector<u8>&) override { }
|
void Deserialize(const std::vector<u8>&) override { }
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
namespace n64 {
|
namespace n64 {
|
||||||
void JIT::add(u32 instr) {
|
void JIT::add(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
movsx(eax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // rs
|
movsx(eax, GPR(dword, RS(instr))); // rs
|
||||||
movsx(ecx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // rt
|
movsx(ecx, GPR(dword, RT(instr))); // rt
|
||||||
CodeGenerator::add(eax, ecx);
|
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) {
|
void JIT::addi(u32 instr) {
|
||||||
if (RT(instr) != 0) [[likely]] {
|
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)));
|
mov(ecx, s32(s16(instr)));
|
||||||
CodeGenerator::add(eax, ecx);
|
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) {
|
void JIT::dadd(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RS(instr))); // rs
|
mov(rax, GPR(qword, RS(instr))); // rs
|
||||||
mov(rcx, GPR(RT(instr))); // rt
|
mov(rcx, GPR(qword, RT(instr))); // rt
|
||||||
CodeGenerator::add(rax, rcx);
|
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) {
|
void JIT::daddu(u32 instr) {
|
||||||
dadd(instr);
|
dadd(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::daddi(u32 instr) {
|
void JIT::daddi(u32 instr) {
|
||||||
if (RT(instr) != 0) [[likely]] {
|
if (RT(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, s64(s16(instr)));
|
mov(rcx, s64(s16(instr)));
|
||||||
CodeGenerator::add(rax, rcx);
|
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) {
|
void JIT::div(u32 instr) {
|
||||||
movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend
|
movsxd(rax, GPR(dword, RS(instr))); // dividend
|
||||||
movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // divisor
|
movsxd(rcx, GPR(dword, RT(instr))); // divisor
|
||||||
cmp(rcx, 0);
|
cmp(rcx, 0);
|
||||||
je("div_divisor==0");
|
je("div_divisor==0");
|
||||||
|
|
||||||
@@ -80,8 +144,8 @@ void JIT::div(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::divu(u32 instr) {
|
void JIT::divu(u32 instr) {
|
||||||
movsxd(rax, dword[rdi + offsetof(Registers, gpr[RS(instr)])]); // dividend
|
movsxd(rax, GPR(dword, RS(instr))); // dividend
|
||||||
movsxd(rcx, dword[rdi + offsetof(Registers, gpr[RT(instr)])]); // divisor
|
movsxd(rcx, GPR(dword, RT(instr))); // divisor
|
||||||
cmp(rcx, 0);
|
cmp(rcx, 0);
|
||||||
je("divu_divisor==0");
|
je("divu_divisor==0");
|
||||||
|
|
||||||
@@ -98,8 +162,8 @@ void JIT::divu(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::ddiv(u32 instr) {
|
void JIT::ddiv(u32 instr) {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, GPR(RT(instr)));
|
mov(rcx, GPR(qword, RT(instr)));
|
||||||
mov(r8, 0x8000000000000000);
|
mov(r8, 0x8000000000000000);
|
||||||
mov(r9, rax);
|
mov(r9, rax);
|
||||||
CodeGenerator::xor_(r9, r8);
|
CodeGenerator::xor_(r9, r8);
|
||||||
@@ -129,8 +193,8 @@ void JIT::ddiv(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::ddivu(u32 instr) {
|
void JIT::ddivu(u32 instr) {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, GPR(RT(instr)));
|
mov(rcx, GPR(qword, RT(instr)));
|
||||||
cmp(rcx, 0);
|
cmp(rcx, 0);
|
||||||
je("ddivu_divisor==0");
|
je("ddivu_divisor==0");
|
||||||
CodeGenerator::div(rcx);
|
CodeGenerator::div(rcx);
|
||||||
@@ -146,40 +210,36 @@ void JIT::ddivu(u32 instr) {
|
|||||||
void JIT::lui(u32 instr) {
|
void JIT::lui(u32 instr) {
|
||||||
u64 val = s64(s16(instr));
|
u64 val = s64(s16(instr));
|
||||||
val <<= 16;
|
val <<= 16;
|
||||||
mov(GPR(RT(instr)), val);
|
mov(GPR(qword, RT(instr)), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::lb(u32 instr) {
|
void JIT::lb(u32 instr) {
|
||||||
mov(rdx, GPR(RS(instr)));
|
mov(rdx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::add(rdx, s64(s16(instr)));
|
CodeGenerator::add(rdx, s64(s16(instr)));
|
||||||
mov(rsi, LOAD);
|
mov(rsi, LOAD);
|
||||||
push(rcx);
|
push(rcx);
|
||||||
lea(rcx, dword[rbp-4]);
|
lea(rcx, dword[rbp-4]);
|
||||||
call(MapVAddr);
|
emitCall(MapVAddr);
|
||||||
pop(rcx);
|
pop(rcx);
|
||||||
cmp(rax, 0);
|
cmp(rax, 0);
|
||||||
je("lb_exception");
|
je("lb_exception");
|
||||||
mov(rsi, dword[rbp-4]);
|
mov(rsi, dword[rbp-4]);
|
||||||
push(rcx);
|
push(rcx);
|
||||||
emitMemberCall(&JIT::Read8, this);
|
emitMemberCall(&Mem::Read<u8>, &mem);
|
||||||
pop(rcx);
|
pop(rcx);
|
||||||
mov(GPR(RT(instr)), rax.cvt8());
|
mov(GPR(qword, RT(instr)), rax.cvt8());
|
||||||
L("lb_exception");
|
L("lb_exception");
|
||||||
mov(rsi, rdx);
|
mov(rsi, rdx);
|
||||||
push(rax);
|
emitCall(HandleTLBException);
|
||||||
call(HandleTLBException);
|
|
||||||
pop(rax);
|
|
||||||
push(rsi);
|
push(rsi);
|
||||||
mov(rdi, REG(byte, cop0.tlbError));
|
mov(rdi, REG(byte, cop0.tlbError));
|
||||||
mov(rsi, LOAD);
|
mov(rsi, LOAD);
|
||||||
call(GetTLBExceptionCode);
|
emitCall(GetTLBExceptionCode);
|
||||||
pop(rsi);
|
pop(rsi);
|
||||||
mov(rsi, rax);
|
mov(rsi, rax);
|
||||||
mov(rdx, 0);
|
mov(rdx, 0);
|
||||||
mov(rcx, 1);
|
mov(rcx, 1);
|
||||||
push(rax);
|
emitCall(FireException);
|
||||||
call(FireException);
|
|
||||||
pop(rax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::lh(u32 instr) {
|
void JIT::lh(u32 instr) {
|
||||||
@@ -554,27 +614,27 @@ void JIT::swr(u32 instr) {
|
|||||||
|
|
||||||
void JIT::ori(u32 instr) {
|
void JIT::ori(u32 instr) {
|
||||||
s64 imm = (u16)instr;
|
s64 imm = (u16)instr;
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::or_(rax, imm);
|
CodeGenerator::or_(rax, imm);
|
||||||
mov(GPR(RT(instr)), rax);
|
mov(GPR(qword, RT(instr)), rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::or_(u32 instr) {
|
void JIT::or_(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, GPR(RT(instr)));
|
mov(rcx, GPR(qword, RT(instr)));
|
||||||
CodeGenerator::or_(rax, rcx);
|
CodeGenerator::or_(rax, rcx);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::nor(u32 instr) {
|
void JIT::nor(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, GPR(RT(instr)));
|
mov(rcx, GPR(qword, RT(instr)));
|
||||||
CodeGenerator::or_(rax, rcx);
|
CodeGenerator::or_(rax, rcx);
|
||||||
not_(rax);
|
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) {
|
void JIT::jal(u32 instr) {
|
||||||
mov(rax, qword[rdi + offsetof(Registers, nextPC)]);
|
mov(rax, qword[rdi + offsetof(Registers, nextPC)]);
|
||||||
mov(GPR(31), rax);
|
mov(GPR(qword, 31), rax);
|
||||||
j(instr);
|
j(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::jalr(u32 instr) {
|
void JIT::jalr(u32 instr) {
|
||||||
mov(byte[rdi + offsetof(Registers, delaySlot)], 1);
|
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);
|
mov(qword[rdi + offsetof(Registers, nextPC)], rax);
|
||||||
|
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, qword[rdi + offsetof(Registers, pc)]);
|
mov(rax, qword[rdi + offsetof(Registers, pc)]);
|
||||||
CodeGenerator::add(rax, 4);
|
CodeGenerator::add(rax, 4);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::slti(u32 instr) {
|
void JIT::slti(u32 instr) {
|
||||||
mov(rax, s64(s16(instr)));
|
mov(rax, s64(s16(instr)));
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
cmp(rcx, rax);
|
cmp(rcx, rax);
|
||||||
setl(GPR(RT(instr)));
|
setl(GPR(qword, RT(instr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sltiu(u32 instr) {
|
void JIT::sltiu(u32 instr) {
|
||||||
mov(rax, s64(s16(instr)));
|
mov(rax, s64(s16(instr)));
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
cmp(rcx, rax);
|
cmp(rcx, rax);
|
||||||
setb(GPR(RT(instr)));
|
setb(GPR(qword, RT(instr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::slt(u32 instr) {
|
void JIT::slt(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, GPR(RT(instr)));
|
mov(rcx, GPR(qword, RT(instr)));
|
||||||
cmp(rax, rcx);
|
cmp(rax, rcx);
|
||||||
setl(GPR(RD(instr)));
|
setl(GPR(qword, RD(instr)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sltu(u32 instr) {
|
void JIT::sltu(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(rcx, GPR(RT(instr)));
|
mov(rcx, GPR(qword, RT(instr)));
|
||||||
cmp(rax, rcx);
|
cmp(rax, rcx);
|
||||||
setb(GPR(RD(instr)));
|
setb(GPR(qword, RD(instr)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::xori(u32 instr) {
|
void JIT::xori(u32 instr) {
|
||||||
s64 imm = (u16)instr;
|
s64 imm = (u16)instr;
|
||||||
mov(rax, (u16)instr);
|
mov(rax, imm);
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::xor_(rcx, rax);
|
CodeGenerator::xor_(rcx, rax);
|
||||||
mov(GPR(RT(instr)), rcx);
|
mov(GPR(qword, RT(instr)), rcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::xor_(u32 instr) {
|
void JIT::xor_(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::xor_(rax, rcx);
|
CodeGenerator::xor_(rax, rcx);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::andi(u32 instr) {
|
void JIT::andi(u32 instr) {
|
||||||
s64 imm = (u16)instr;
|
s64 imm = (u16)instr;
|
||||||
mov(rax, (u16)instr);
|
mov(rax, (u16)instr);
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(rcx, rax);
|
CodeGenerator::and_(rcx, rax);
|
||||||
mov(GPR(RT(instr)), rcx);
|
mov(GPR(qword, RT(instr)), rcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::and_(u32 instr) {
|
void JIT::and_(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(rax, rcx);
|
CodeGenerator::and_(rax, rcx);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sll(u32 instr) {
|
void JIT::sll(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sal(rax, sa);
|
sal(rax, sa);
|
||||||
movsxd(rcx, eax);
|
movsxd(rcx, eax);
|
||||||
mov(GPR(RD(instr)), rcx);
|
mov(GPR(qword, RD(instr)), rcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sllv(u32 instr) {
|
void JIT::sllv(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(cl, 0x1F);
|
CodeGenerator::and_(cl, 0x1F);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sal(rax, cl);
|
sal(rax, cl);
|
||||||
movsxd(rcx, eax);
|
movsxd(rcx, eax);
|
||||||
mov(GPR(RD(instr)), rcx);
|
mov(GPR(qword, RD(instr)), rcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsll32(u32 instr) {
|
void JIT::dsll32(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f) + 32;
|
u8 sa = ((instr >> 6) & 0x1f) + 32;
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sal(rax, sa);
|
sal(rax, sa);
|
||||||
mov(GPR(RT(instr)), rax);
|
mov(GPR(qword, RT(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsll(u32 instr) {
|
void JIT::dsll(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sal(rax, sa);
|
sal(rax, sa);
|
||||||
mov(GPR(RT(instr)), rax);
|
mov(GPR(qword, RT(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsllv(u32 instr) {
|
void JIT::dsllv(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(cl, 63);
|
CodeGenerator::and_(cl, 63);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sal(rax, cl);
|
sal(rax, cl);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::srl(u32 instr) {
|
void JIT::srl(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
CodeGenerator::shr(rax, sa);
|
CodeGenerator::shr(rax, sa);
|
||||||
movsxd(rcx, eax);
|
movsxd(rcx, eax);
|
||||||
mov(GPR(RD(instr)), rcx);
|
mov(GPR(qword, RD(instr)), rcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::srlv(u32 instr) {
|
void JIT::srlv(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(cl, 0x1F);
|
CodeGenerator::and_(cl, 0x1F);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
shr(rax, cl);
|
shr(rax, cl);
|
||||||
movsxd(rcx, eax);
|
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) {
|
void JIT::dsrl(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
CodeGenerator::shr(rax, sa);
|
CodeGenerator::shr(rax, sa);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsrlv(u32 instr) {
|
void JIT::dsrlv(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(cl, 63);
|
CodeGenerator::and_(cl, 63);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
shr(rax, cl);
|
shr(rax, cl);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsrl32(u32 instr) {
|
void JIT::dsrl32(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f) + 32;
|
u8 sa = ((instr >> 6) & 0x1f) + 32;
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
CodeGenerator::shr(rax, sa);
|
CodeGenerator::shr(rax, sa);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sra(u32 instr) {
|
void JIT::sra(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sar(rax, sa);
|
sar(rax, sa);
|
||||||
movsxd(rcx, eax);
|
movsxd(rcx, eax);
|
||||||
mov(GPR(RD(instr)), rcx);
|
mov(GPR(qword, RD(instr)), rcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::srav(u32 instr) {
|
void JIT::srav(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(cl, 0x1F);
|
CodeGenerator::and_(cl, 0x1F);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sar(rax, cl);
|
sar(rax, cl);
|
||||||
movsxd(rcx, eax);
|
movsxd(rcx, eax);
|
||||||
mov(GPR(RD(instr)), rcx);
|
mov(GPR(qword, RD(instr)), rcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsra(u32 instr) {
|
void JIT::dsra(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sar(rax, sa);
|
sar(rax, sa);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsrav(u32 instr) {
|
void JIT::dsrav(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::and_(cl, 63);
|
CodeGenerator::and_(cl, 63);
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sar(rax, cl);
|
sar(rax, cl);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsra32(u32 instr) {
|
void JIT::dsra32(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
u8 sa = ((instr >> 6) & 0x1f) + 32;
|
u8 sa = ((instr >> 6) & 0x1f) + 32;
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
sar(rax, sa);
|
sar(rax, sa);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::jr(u32 instr) {
|
void JIT::jr(u32 instr) {
|
||||||
mov(rax, GPR(RS(instr)));
|
mov(rax, GPR(qword, RS(instr)));
|
||||||
mov(REG(byte, delaySlot), 1);
|
mov(REG(byte, delaySlot), 1);
|
||||||
mov(REG(qword, nextPC), rax);
|
mov(REG(qword, nextPC), rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::dsub(u32 instr) {
|
void JIT::dsub(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(rax, GPR(RT(instr)));
|
mov(rax, GPR(qword, RT(instr)));
|
||||||
mov(rcx, GPR(RS(instr)));
|
mov(rcx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::sub(rcx, rax);
|
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) {
|
void JIT::sub(u32 instr) {
|
||||||
if (RD(instr) != 0) [[likely]] {
|
if (RD(instr) != 0) [[likely]] {
|
||||||
mov(eax, GPR(RT(instr)));
|
mov(eax, GPR(qword, RT(instr)));
|
||||||
mov(ecx, GPR(RS(instr)));
|
mov(ecx, GPR(qword, RS(instr)));
|
||||||
CodeGenerator::sub(ecx, eax);
|
CodeGenerator::sub(ecx, eax);
|
||||||
movsxd(rax, ecx);
|
movsxd(rax, ecx);
|
||||||
mov(GPR(RD(instr)), rax);
|
mov(GPR(qword, RD(instr)), rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user