This commit is contained in:
Simone
2023-11-23 10:07:02 +01:00
parent 25cfd49e64
commit 8fb79fefd5
4 changed files with 165 additions and 310 deletions

View File

@@ -83,15 +83,15 @@ _epilogue:
} }
int JIT::Step() { int JIT::Step() {
if(!blocks[regs.pc >> 20]) { if(!blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)]) {
blocks[regs.pc >> 20] = (Fn*)calloc(4096, sizeof(Fn)); blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)] = (Fn*)calloc(BLOCKCACHE_INNER_SIZE, 1);
blocks[regs.pc >> 20][regs.pc & 0xfff] = Recompile(); blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)] = Recompile();
} }
if (!blocks[regs.pc >> 20][regs.pc & 0xfff]) { if (!blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)]) {
blocks[regs.pc >> 20][regs.pc & 0xfff] = Recompile(); blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)] = Recompile();
} }
return blocks[regs.pc >> 20][regs.pc & 0xfff](); return blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)]();
} }
} }

View File

@@ -9,6 +9,14 @@ namespace n64 {
using Fn = int(*)(); using Fn = int(*)();
#define GPR(x) qword[rdi + offsetof(Registers, gpr[(x)])] #define GPR(x) qword[rdi + offsetof(Registers, gpr[(x)])]
#define REG(ptr, member) ptr[rdi + offsetof(Registers, member)] #define REG(ptr, member) ptr[rdi + offsetof(Registers, member)]
// 4KiB aligned pages
#define BLOCKCACHE_OUTER_SHIFT 12
#define BLOCKCACHE_PAGE_SIZE (1 << BLOCKCACHE_OUTER_SHIFT)
#define BLOCKCACHE_OUTER_SIZE (0x80000000 >> BLOCKCACHE_OUTER_SHIFT)
// word aligned instructions
#define BLOCKCACHE_INNER_SIZE (BLOCKCACHE_PAGE_SIZE >> 2)
#define BLOCKCACHE_INNER_INDEX(physical) (((physical) & (BLOCKCACHE_PAGE_SIZE - 1)) >> 2)
#define BLOCKCACHE_OUTER_INDEX(physical) ((physical) >> BLOCKCACHE_OUTER_SHIFT)
struct JIT : BaseCPU, Xbyak::CodeGenerator { struct JIT : BaseCPU, Xbyak::CodeGenerator {
JIT(); JIT();
@@ -27,7 +35,7 @@ private:
void emitMemberCall(T func, void* thisObj) { void emitMemberCall(T func, void* thisObj) {
void* funcPtr; void* 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");
std::memcpy(&funcPtr, &func, sizeof(T)); std::memcpy(&funcPtr, &func, sizeof(T));
#elif defined(ABI_UNIX) #elif defined(ABI_UNIX)
@@ -38,7 +46,7 @@ private:
thisPtr += tmpArr[1]; thisPtr += tmpArr[1];
#else #else
Util::panic("Huh?!"); Util::panic("Huh?!");
#endif*/ #endif
push(rdi); push(rdi);
if(thisPtr == reinterpret_cast<uintptr_t>(this)) { if(thisPtr == reinterpret_cast<uintptr_t>(this)) {
@@ -91,11 +99,8 @@ private:
ret(); ret();
} }
Fn* blocks[0x80000]{}; static u8 codecache[1 << 25] __attribute__((aligned(4096)));
Fn* blocks[BLOCKCACHE_OUTER_SIZE]{};
enum BranchCond {
LT, GT, GE, LE, EQ, NE
};
u8 Read8(u64 addr) { u8 Read8(u64 addr) {
return mem.Read<u8>(regs, addr); return mem.Read<u8>(regs, addr);
@@ -114,24 +119,22 @@ private:
void addiu(u32); void addiu(u32);
void andi(u32); void andi(u32);
void and_(u32); void and_(u32);
void emitCondition(const std::string&, BranchCond); void bltz(u32);
template <class T> void bgez(u32);
void branch(const Xbyak::Reg64&, const T&, s64, BranchCond); void bltzl(u32);
void bgezl(u32);
template <class T> void bltzal(u32);
void branch_likely(const Xbyak::Reg64&, const T&, s64, BranchCond); void bgezal(u32);
void bltzall(u32);
template <class T> void bgezall(u32);
void b(u32, const Xbyak::Reg64&, const T&, BranchCond); void beq(u32);
void bne(u32);
template <class T> void blez(u32);
void blink(u32, const Xbyak::Reg64&, const T&, BranchCond); void bgtz(u32);
void beql(u32);
template <class T> void bnel(u32);
void bl(u32, const Xbyak::Reg64&, const T&, BranchCond); void blezl(u32);
void bgtzl(u32);
template <class T>
void bllink(u32, const Xbyak::Reg64&, const T&, BranchCond);
void dadd(u32); void dadd(u32);
void daddu(u32); void daddu(u32);
void daddi(u32); void daddi(u32);
@@ -200,7 +203,18 @@ private:
void srav(u32); void srav(u32);
void srl(u32); void srl(u32);
void srlv(u32); void srlv(u32);
void trap(bool); void tgei(u32);
void tgeiu(u32);
void tlti(u32);
void tltiu(u32);
void teqi(u32);
void tnei(u32);
void tge(u32);
void tgeu(u32);
void tlt(u32);
void tltu(u32);
void teq(u32);
void tne(u32);
void or_(u32); void or_(u32);
void ori(u32); void ori(u32);
void xor_(u32); void xor_(u32);

View File

@@ -6,62 +6,62 @@ void JIT::special(u32 instr) {
u8 mask = (instr & 0x3F); u8 mask = (instr & 0x3F);
// 00rr_rccc // 00rr_rccc
switch (mask) { // TODO: named constants for clearer code switch (mask) { // TODO: named constants for clearer code
case 0: case SLL:
if (instr != 0) { if (instr != 0) {
sll(instr); sll(instr);
} }
break; break;
case 0x02: srl(instr); break; case SRL: srl(instr); break;
case 0x03: sra(instr); break; case SRA: sra(instr); break;
case 0x04: sllv(instr); break; case SLLV: sllv(instr); break;
case 0x06: srlv(instr); break; case SRLV: srlv(instr); break;
case 0x07: srav(instr); break; case SRAV: srav(instr); break;
case 0x08: jr(instr); break; case JR: jr(instr); break;
case 0x09: jalr(instr); break; case JALR: jalr(instr); break;
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break; case SYSCALL: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break; case BREAK: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
case 0x0F: break; // SYNC case SYNC: break; // SYNC
case 0x10: mfhi(instr); break; case MFHI: mfhi(instr); break;
case 0x11: mthi(instr); break; case MTHI: mthi(instr); break;
case 0x12: mflo(instr); break; case MFLO: mflo(instr); break;
case 0x13: mtlo(instr); break; case MTLO: mtlo(instr); break;
case 0x14: dsllv(instr); break; case DSLLV: dsllv(instr); break;
case 0x16: dsrlv(instr); break; case DSRLV: dsrlv(instr); break;
case 0x17: dsrav(instr); break; case DSRAV: dsrav(instr); break;
case 0x18: mult(instr); break; case MULT: mult(instr); break;
case 0x19: multu(instr); break; case MULTU: multu(instr); break;
case 0x1A: div(instr); break; case DIV: div(instr); break;
case 0x1B: divu(instr); break; case DIVU: divu(instr); break;
case 0x1C: dmult(instr); break; case DMULT: dmult(instr); break;
case 0x1D: dmultu(instr); break; case DMULTU: dmultu(instr); break;
case 0x1E: ddiv(instr); break; case DDIV: ddiv(instr); break;
case 0x1F: ddivu(instr); break; case DDIVU: ddivu(instr); break;
case 0x20: add(instr); break; case ADD: add(instr); break;
case 0x21: addu(instr); break; case ADDU: addu(instr); break;
case 0x22: sub(instr); break; case SUB: sub(instr); break;
case 0x23: subu(instr); break; case SUBU: subu(instr); break;
case 0x24: and_(instr); break; case AND: and_(instr); break;
case 0x25: or_(instr); break; case OR: or_(instr); break;
case 0x26: xor_(instr); break; case XOR: xor_(instr); break;
case 0x27: nor(instr); break; case NOR: nor(instr); break;
case 0x2A: slt(instr); break; case SLT: slt(instr); break;
case 0x2B: sltu(instr); break; case SLTU: sltu(instr); break;
case 0x2C: dadd(instr); break; case DADD: dadd(instr); break;
case 0x2D: daddu(instr); break; case DADDU: daddu(instr); break;
case 0x2E: dsub(instr); break; case DSUB: dsub(instr); break;
case 0x2F: dsubu(instr); break; case DSUBU: dsubu(instr); break;
case 0x30: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; case TGE: tge(instr); break;
case 0x31: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; case TGEU: tgeu(instr); break;
case 0x32: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; case TLT: tlt(instr); break;
case 0x33: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; case TLTU: tltu(instr); break;
case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; case TEQ: teq(instr); break;
case 0x36: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; case TNE: tne(instr); break;
case 0x38: dsll(instr); break; case DSLL: dsll(instr); break;
case 0x3A: dsrl(instr); break; case DSRL: dsrl(instr); break;
case 0x3B: dsra(instr); break; case DSRA: dsra(instr); break;
case 0x3C: dsll32(instr); break; case DSLL32: dsll32(instr); break;
case 0x3E: dsrl32(instr); break; case DSRL32: dsrl32(instr); break;
case 0x3F: dsra32(instr); break; case DSRA32: dsra32(instr); break;
default: default:
Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
} }
@@ -71,44 +71,20 @@ void JIT::regimm(u32 instr) {
u8 mask = ((instr >> 16) & 0x1F); u8 mask = ((instr >> 16) & 0x1F);
// 000r_rccc // 000r_rccc
switch (mask) { // TODO: named constants for clearer code switch (mask) { // TODO: named constants for clearer code
case 0x00: { case BLTZ: bltz(instr); break;
mov(rax, GPR(RS(instr))); case BGEZ: bgez(instr); break;
b(instr, rax, 0, LT); case BLTZL: bltzl(instr); break;
} break; case BGEZL: bgezl(instr); break;
case 0x01: { case TGEI: tgei(instr); break;
mov(rax, GPR(RS(instr))); case TGEIU: tgeiu(instr); break;
b(instr, rax, 0, GE); case TLTI: tlti(instr); break;
} break; case TLTIU: tltiu(instr); break;
case 0x02: { case TEQI: teqi(instr); break;
mov(rax, GPR(RS(instr))); case TNEI: tnei(instr); break;
bl(instr, rax, 0, LT); case BLTZAL: bltzal(instr); break;
} break; case BGEZAL: bgezal(instr); break;
case 0x03: { case BLTZALL: bltzall(instr); break;
mov(rax, GPR(RS(instr))); case BGEZALL: bgezall(instr); break;
bl(instr, rax, 0, GE);
} break;
case 0x08: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break;
case 0x09: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break;
case 0x0A: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break;
case 0x0B: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break;
case 0x0C: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break;
case 0x0E: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break;
case 0x10: {
mov(rax, GPR(RS(instr)));
blink(instr, rax, 0, LT);
} break;
case 0x11: {
mov(rax, GPR(RS(instr)));
blink(instr, rax, 0, GE);
} break;
case 0x12: {
mov(rax, GPR(RS(instr)));
bllink(instr, rax, 0, LT);
} break;
case 0x13: {
mov(rax, GPR(RS(instr)));
bllink(instr, rax, 0, GE);
} break;
default: default:
Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
} }
@@ -135,88 +111,60 @@ void JIT::Emit(u32 instr) {
u8 mask = (instr >> 26) & 0x3f; u8 mask = (instr >> 26) & 0x3f;
// 00rr_rccc // 00rr_rccc
switch(mask) { // TODO: named constants for clearer code switch(mask) { // TODO: named constants for clearer code
case 0x00: special(instr); break; case SPECIAL: special(instr); break;
case 0x01: regimm(instr); break; case REGIMM: regimm(instr); break;
case 0x02: j(instr); break; case J: j(instr); break;
case 0x03: jal(instr); break; case JAL: jal(instr); break;
case 0x04: { case BEQ: beq(instr); break;
mov(rax, GPR(RS(instr))); case BNE: bne(instr); break;
mov(rcx, GPR(RT(instr))); case BLEZ: blez(instr); break;
b(instr, rax, rcx, EQ); case BGTZ: bgtz(instr); break;
} break; case ADDI: addi(instr); break;
case 0x05: { case ADDIU: addiu(instr); break;
mov(rax, GPR(RS(instr))); case SLTI: slti(instr); break;
mov(rcx, GPR(RT(instr))); case SLTIU: sltiu(instr); break;
b(instr, rax, rcx, NE); case ANDI: andi(instr); break;
} break; case ORI: ori(instr); break;
case 0x06: { case XORI: xori(instr); break;
mov(rax, GPR(RS(instr))); case LUI: lui(instr); break;
b(instr, rax, 0, LE); case COP0: regs.cop0.decode(*this, instr); break;
} break; case COP1: regs.cop1.decode(*this, instr); break;
case 0x07: { case COP2: cop2Decode(instr); break;
mov(rax, GPR(RS(instr))); case BEQL: beql(instr); break;
b(instr, rax, 0, GT); case BNEL: bnel(instr); break;
} break; case BLEZL: blezl(instr); break;
case 0x08: addi(instr); break; case BGTZL: bgtzl(instr); break;
case 0x09: addiu(instr); break; case DADDI: daddi(instr); break;
case 0x0A: slti(instr); break; case DADDIU: daddiu(instr); break;
case 0x0B: sltiu(instr); break; case LDL: ldl(instr); break;
case 0x0C: andi(instr); break; case LDR: ldr(instr); break;
case 0x0D: ori(instr); break;
case 0x0E: xori(instr); break;
case 0x0F: lui(instr); break;
case 0x10: regs.cop0.decode(*this, instr); break;
case 0x11: regs.cop1.decode(*this, instr); break;
case 0x12: cop2Decode(instr); break;
case 0x14: {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
bl(instr, rax, rcx, EQ);
} break;
case 0x15: {
mov(rax, GPR(RS(instr)));
mov(rcx, GPR(RT(instr)));
bl(instr, rax, rcx, NE);
} break;
case 0x16: {
mov(rax, GPR(RS(instr)));
bl(instr, rax, 0, LE);
} break;
case 0x17: {
mov(rax, GPR(RS(instr)));
bl(instr, rax, 0, GT);
} break;
case 0x18: daddi(instr); break;
case 0x19: daddiu(instr); break;
case 0x1A: ldl(instr); break;
case 0x1B: ldr(instr); break;
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
case 0x20: lb(instr); break; case LB: lb(instr); break;
case 0x21: lh(instr); break; case LH: lh(instr); break;
case 0x22: lwl(instr); break; case LWL: lwl(instr); break;
case 0x23: lw(instr); break; case LW: lw(instr); break;
case 0x24: lbu(instr); break; case LBU: lbu(instr); break;
case 0x25: lhu(instr); break; case LHU: lhu(instr); break;
case 0x26: lwr(instr); break; case LWR: lwr(instr); break;
case 0x27: lwu(instr); break; case LWU: lwu(instr); break;
case 0x28: sb(instr); break; case SB: sb(instr); break;
case 0x29: sh(instr); break; case SH: sh(instr); break;
case 0x2A: swl(instr); break; case SWL: swl(instr); break;
case 0x2B: sw(instr); break; case SW: sw(instr); break;
case 0x2C: sdl(instr); break; case SDL: sdl(instr); break;
case 0x2D: sdr(instr); break; case SDR: sdr(instr); break;
case 0x2E: swr(instr); break; case SWR: swr(instr); break;
case 0x2F: break; // CACHE case CACHE: break; // CACHE
case 0x30: ll(instr); break; case LL: ll(instr); break;
case 0x31: regs.cop1.lwc1(*this, mem, instr); break; case LWC1: regs.cop1.lwc1(*this, mem, instr); break;
case 0x34: lld(instr); break; case LLD: lld(instr); break;
case 0x35: regs.cop1.ldc1(*this, mem, instr); break; case LDC1: regs.cop1.ldc1(*this, mem, instr); break;
case 0x37: ld(instr); break; case LD: ld(instr); break;
case 0x38: sc(instr); break; case SC: sc(instr); break;
case 0x39: regs.cop1.swc1(*this, mem, instr); break; case SWC1: regs.cop1.swc1(*this, mem, instr); break;
case 0x3C: scd(instr); break; case SCD: scd(instr); break;
case 0x3D: regs.cop1.sdc1(*this, mem, instr); break; case SDC1: regs.cop1.sdc1(*this, mem, instr); break;
case 0x3F: sd(instr); break; case SD: sd(instr); break;
default: default:
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, (u64)regs.oldPC); Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, (u64)regs.oldPC);
} }

View File

@@ -143,107 +143,6 @@ void JIT::ddivu(u32 instr) {
L("ddivu_exit"); L("ddivu_exit");
} }
void JIT::emitCondition(const std::string& name, BranchCond cond) {
switch(cond) {
case LT:
jnl(name);
break;
case GT:
jng(name);
break;
case GE:
jnge(name);
break;
case LE:
jnle(name);
break;
case EQ:
jne(name);
break;
case NE:
je(name);
break;
}
}
template <class T>
void JIT::branch(const Xbyak::Reg64& op1, const T& op2, s64 offset, BranchCond cond) {
cmp(op1, op2);
emitCondition("branch_false", cond);
mov(byte[rdi + offsetof(Registers, delaySlot)], 1);
mov(rax, qword[rdi + offsetof(Registers, pc)]);
CodeGenerator::add(rax, offset);
mov(qword[rdi + offsetof(Registers, nextPC)], rax);
L("branch_false");
}
template void JIT::branch<Xbyak::Reg64>(const Xbyak::Reg64& op1, const Xbyak::Reg64& op2, s64 offset, BranchCond cond);
template void JIT::branch<int>(const Xbyak::Reg64& op1, const int& op2, s64 offset, BranchCond cond);
template <class T>
void JIT::branch_likely(const Xbyak::Reg64& op1, const T& op2, s64 offset, BranchCond cond) {
mov(rax, qword[rdi + offsetof(Registers, pc)]);
cmp(op1, op2);
emitCondition("branch_likely_false", cond);
mov(byte[rdi + offsetof(Registers, delaySlot)], 1);
CodeGenerator::add(rax, offset);
mov(qword[rdi + offsetof(Registers, nextPC)], rax);
jmp("branch_likely_exit");
L("branch_likely_false");
mov(qword[rdi + offsetof(Registers, oldPC)], rax);
mov(rcx, qword[rdi + offsetof(Registers, nextPC)]);
mov(qword[rdi + offsetof(Registers, pc)], rcx);
CodeGenerator::add(rcx, 4);
mov(qword[rdi + offsetof(Registers, nextPC)], rcx);
L("branch_likely_exit");
}
template void JIT::branch_likely<Xbyak::Reg64>(const Xbyak::Reg64& op1, const Xbyak::Reg64& op2, s64 offset, BranchCond cond);
template void JIT::branch_likely<int>(const Xbyak::Reg64& op1, const int& op2, s64 offset, BranchCond cond);
template <class T>
void JIT::b(u32 instr, const Xbyak::Reg64& op1, const T& op2, BranchCond cond) {
s16 imm = instr;
s64 offset = u64((s64)imm) << 2;
branch(op1, op2, offset, cond);
}
template void JIT::b<Xbyak::Reg64>(u32 instr, const Xbyak::Reg64& op1, const Xbyak::Reg64& op2, BranchCond cond);
template void JIT::b<int>(u32 instr, const Xbyak::Reg64& op1, const int& op2, BranchCond cond);
template <class T>
void JIT::blink(u32 instr, const Xbyak::Reg64& op1, const T& op2, BranchCond cond) {
s16 imm = instr;
s64 offset = u64((s64)imm) << 2;
mov(rcx, qword[rdi + offsetof(Registers, nextPC)]);
mov(GPR(31), rcx);
branch(op1, op2, offset, cond);
}
template void JIT::blink<Xbyak::Reg64>(u32 instr, const Xbyak::Reg64& op1, const Xbyak::Reg64& op2, BranchCond cond);
template void JIT::blink<int>(u32 instr, const Xbyak::Reg64& op1, const int& op2, BranchCond cond);
template <class T>
void JIT::bl(u32 instr, const Xbyak::Reg64& op1, const T& op2, BranchCond cond) {
s16 imm = instr;
s64 offset = u64((s64)imm) << 2;
branch_likely(op1, op2, offset, cond);
}
template void JIT::bl<Xbyak::Reg64>(u32 instr, const Xbyak::Reg64& op1, const Xbyak::Reg64& op2, BranchCond cond);
template void JIT::bl<int>(u32 instr, const Xbyak::Reg64& op1, const int& op2, BranchCond cond);
template <class T>
void JIT::bllink(u32 instr, const Xbyak::Reg64& op1, const T& op2, BranchCond cond) {
mov(rcx, qword[rdi + offsetof(Registers, nextPC)]);
mov(GPR(31), rcx);
s16 imm = instr;
s64 offset = u64((s64)imm) << 2;
branch_likely(op1, op2, offset, cond);
}
template void JIT::bllink<Xbyak::Reg64>(u32 instr, const Xbyak::Reg64& op1, const Xbyak::Reg64& op2, BranchCond cond);
template void JIT::bllink<int>(u32 instr, const Xbyak::Reg64& op1, const int& op2, BranchCond cond);
void JIT::lui(u32 instr) { void JIT::lui(u32 instr) {
u64 val = s64(s16(instr)); u64 val = s64(s16(instr));
val <<= 16; val <<= 16;
@@ -1003,12 +902,6 @@ void JIT::mthi(u32 instr) {
regs.hi = regs.gpr[RS(instr)]; regs.hi = regs.gpr[RS(instr)];
} }
void JIT::trap(bool cond) {
if(cond) {
FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
}
}
void JIT::mtc2(u32 instr) { void JIT::mtc2(u32 instr) {
} }