This commit is contained in:
2026-03-23 12:11:07 +01:00
commit e64eb40b38
4573 changed files with 3117439 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
file(GLOB_RECURSE SOURCES *.cpp)
file(GLOB_RECURSE HEADERS *.hpp)
add_library(jit ${SOURCES} ${HEADERS})
+465
View File
@@ -0,0 +1,465 @@
#include <JIT.hpp>
#include <Instruction.hpp>
namespace n64 {
void JIT::special(const Instruction instr) {
// 00rr_rccc
switch (instr.special()) {
case Instruction::SLL:
if (instr != 0) {
sll(instr);
}
break;
case Instruction::SRL:
srl(instr);
break;
case Instruction::SRA:
sra(instr);
break;
case Instruction::SLLV:
sllv(instr);
break;
case Instruction::SRLV:
srlv(instr);
break;
case Instruction::SRAV:
srav(instr);
break;
case Instruction::JR:
jr(instr);
break;
case Instruction::JALR:
jalr(instr);
break;
case Instruction::SYSCALL:
regs.cop0.FireException(ExceptionCode::Syscall, 0, regs.oldPC);
break;
case Instruction::BREAK:
regs.cop0.FireException(ExceptionCode::Breakpoint, 0, regs.oldPC);
break;
case Instruction::SYNC:
break; // SYNC
case Instruction::MFHI:
mfhi(instr);
break;
case Instruction::MTHI:
mthi(instr);
break;
case Instruction::MFLO:
mflo(instr);
break;
case Instruction::MTLO:
mtlo(instr);
break;
case Instruction::DSLLV:
dsllv(instr);
break;
case Instruction::DSRLV:
dsrlv(instr);
break;
case Instruction::DSRAV:
dsrav(instr);
break;
case Instruction::MULT:
mult(instr);
break;
case Instruction::MULTU:
multu(instr);
break;
case Instruction::DIV:
div(instr);
break;
case Instruction::DIVU:
divu(instr);
break;
case Instruction::DMULT:
dmult(instr);
break;
case Instruction::DMULTU:
dmultu(instr);
break;
case Instruction::DDIV:
ddiv(instr);
break;
case Instruction::DDIVU:
ddivu(instr);
break;
case Instruction::ADD:
add(instr);
break;
case Instruction::ADDU:
addu(instr);
break;
case Instruction::SUB:
sub(instr);
break;
case Instruction::SUBU:
subu(instr);
break;
case Instruction::AND:
and_(instr);
break;
case Instruction::OR:
or_(instr);
break;
case Instruction::XOR:
xor_(instr);
break;
case Instruction::NOR:
nor(instr);
break;
case Instruction::SLT:
slt(instr);
break;
case Instruction::SLTU:
sltu(instr);
break;
case Instruction::DADD:
dadd(instr);
break;
case Instruction::DADDU:
daddu(instr);
break;
case Instruction::DSUB:
dsub(instr);
break;
case Instruction::DSUBU:
dsubu(instr);
break;
case Instruction::TGE:
trap(regs.Read<s64>(instr.rs()) >= regs.Read<s64>(instr.rt()));
break;
case Instruction::TGEU:
trap(regs.Read<u64>(instr.rs()) >= regs.Read<u64>(instr.rt()));
break;
case Instruction::TLT:
trap(regs.Read<s64>(instr.rs()) < regs.Read<s64>(instr.rt()));
break;
case Instruction::TLTU:
trap(regs.Read<u64>(instr.rs()) < regs.Read<u64>(instr.rt()));
break;
case Instruction::TEQ:
trap(regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
break;
case Instruction::TNE:
trap(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
break;
case Instruction::DSLL:
dsll(instr);
break;
case Instruction::DSRL:
dsrl(instr);
break;
case Instruction::DSRA:
dsra(instr);
break;
case Instruction::DSLL32:
dsll32(instr);
break;
case Instruction::DSRL32:
dsrl32(instr);
break;
case Instruction::DSRA32:
dsra32(instr);
break;
default:
panic("Unimplemented special {} ({:08X}) (pc: {:016X})", instr.special(), u32(instr),
static_cast<u64>(regs.oldPC));
}
}
void JIT::regimm(const Instruction instr) {
// 000r_rccc
switch (instr.regimm()) {
case Instruction::BLTZ:
bltz(instr);
break;
case Instruction::BGEZ:
bgez(instr);
break;
case Instruction::BLTZL:
bltzl(instr);
break;
case Instruction::BGEZL:
bgezl(instr);
break;
case Instruction::TGEI:
trap(regs.Read<s64>(instr.rs()) >= static_cast<s64>(static_cast<s16>(instr)));
break;
case Instruction::TGEIU:
trap(regs.Read<u64>(instr.rs()) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
break;
case Instruction::TLTI:
trap(regs.Read<s64>(instr.rs()) < static_cast<s64>(static_cast<s16>(instr)));
break;
case Instruction::TLTIU:
trap(regs.Read<u64>(instr.rs()) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
break;
case Instruction::TEQI:
trap(regs.Read<s64>(instr.rs()) == static_cast<s64>(static_cast<s16>(instr)));
break;
case Instruction::TNEI:
trap(regs.Read<s64>(instr.rs()) != static_cast<s64>(static_cast<s16>(instr)));
break;
case Instruction::BLTZAL:
bltzal(instr);
break;
case Instruction::BGEZAL:
bgezal(instr);
break;
case Instruction::BLTZALL:
bltzall(instr);
break;
case Instruction::BGEZALL:
bgezall(instr);
break;
default:
panic("Unimplemented regimm {} ({:08X}) (pc: {:016X})", instr.regimm(), u32(instr),
static_cast<u64>(regs.oldPC));
}
}
void JIT::Emit(const Instruction instr) {
switch (instr.opcode()) {
case Instruction::SPECIAL:
special(instr);
break;
case Instruction::REGIMM:
regimm(instr);
break;
case Instruction::J:
j(instr);
break;
case Instruction::JAL:
jal(instr);
break;
case Instruction::BEQ:
beq(instr);
break;
case Instruction::BNE:
bne(instr);
break;
case Instruction::BLEZ:
blez(instr);
break;
case Instruction::BGTZ:
bgtz(instr);
break;
case Instruction::ADDI:
addi(instr);
break;
case Instruction::ADDIU:
addiu(instr);
break;
case Instruction::SLTI:
slti(instr);
break;
case Instruction::SLTIU:
sltiu(instr);
break;
case Instruction::ANDI:
andi(instr);
break;
case Instruction::ORI:
ori(instr);
break;
case Instruction::XORI:
xori(instr);
break;
case Instruction::LUI:
lui(instr);
break;
case Instruction::COP0:
switch (instr.cop_rs()) {
case 0x00:
code.mov(code.ARG2, instr);
emitMemberFunctionCall(&Cop0::mfc0, &regs.cop0);
break;
case 0x01:
code.mov(code.ARG2, instr);
emitMemberFunctionCall(&Cop0::dmfc0, &regs.cop0);
break;
case 0x04:
code.mov(code.ARG2, instr);
emitMemberFunctionCall(&Cop0::mtc0, &regs.cop0);
break;
case 0x05:
code.mov(code.ARG2, instr);
emitMemberFunctionCall(&Cop0::dmtc0, &regs.cop0);
break;
case 0x10 ... 0x1F:
switch (instr.cop_funct()) {
case 0x01:
emitMemberFunctionCall(&Cop0::tlbr, &regs.cop0);
break;
case 0x02:
code.mov(code.ARG2, COP0_REG_INDEX);
emitMemberFunctionCall(&Cop0::GetReg32, &regs.cop0);
code.mov(code.ARG2, code.rax);
code.and_(code.ARG2, 0x3F);
emitMemberFunctionCall(&Cop0::tlbw, &regs.cop0);
break;
case 0x06:
emitMemberFunctionCall(&Cop0::GetRandom, &regs.cop0);
code.mov(code.ARG2, code.rax);
emitMemberFunctionCall(&Cop0::tlbw, &regs.cop0);
break;
case 0x08:
emitMemberFunctionCall(&Cop0::tlbp, &regs.cop0);
break;
case 0x18:
emitMemberFunctionCall(&Cop0::eret, &regs.cop0);
break;
default:
panic("Unimplemented COP0 function {} ({:08X}) ({:016X})", instr.cop_funct(), u32(instr),
regs.oldPC);
}
break;
default:
panic("Unimplemented COP0 instruction {}", instr.cop_rs());
}
break;
case Instruction::COP1:
{
if (instr.cop_rs() == 0x08) {
switch (instr.cop_rt()) {
case 0:
// if (!regs.cop1.CheckFPUUsable())
// return;
bfc0(instr);
break;
case 1:
// if (!regs.cop1.CheckFPUUsable())
// return;
bfc1(instr);
break;
case 2:
// if (!regs.cop1.CheckFPUUsable())
// return;
blfc0(instr);
break;
case 3:
// if (!regs.cop1.CheckFPUUsable())
// return;
blfc1(instr);
break;
default:
panic("Undefined BC COP1 {:02X}", instr.cop_rt());
}
break;
}
regs.cop1.decode(instr);
}
break;
case Instruction::COP2:
break;
case Instruction::BEQL:
beql(instr);
break;
case Instruction::BNEL:
bnel(instr);
break;
case Instruction::BLEZL:
blezl(instr);
break;
case Instruction::BGTZL:
bgtzl(instr);
break;
case Instruction::DADDI:
daddi(instr);
break;
case Instruction::DADDIU:
daddiu(instr);
break;
case Instruction::LDL:
ldl(instr);
break;
case Instruction::LDR:
ldr(instr);
break;
case 0x1F:
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
break;
case Instruction::LB:
lb(instr);
break;
case Instruction::LH:
lh(instr);
break;
case Instruction::LWL:
lwl(instr);
break;
case Instruction::LW:
lw(instr);
break;
case Instruction::LBU:
lbu(instr);
break;
case Instruction::LHU:
lhu(instr);
break;
case Instruction::LWR:
lwr(instr);
break;
case Instruction::LWU:
lwu(instr);
break;
case Instruction::SB:
sb(instr);
break;
case Instruction::SH:
sh(instr);
break;
case Instruction::SWL:
swl(instr);
break;
case Instruction::SW:
sw(instr);
break;
case Instruction::SDL:
sdl(instr);
break;
case Instruction::SDR:
sdr(instr);
break;
case Instruction::SWR:
swr(instr);
break;
case Instruction::CACHE:
break; // CACHE
case Instruction::LL:
ll(instr);
break;
case Instruction::LWC1:
lwc1(instr);
break;
case Instruction::LLD:
lld(instr);
break;
case Instruction::LDC1:
ldc1(instr);
break;
case Instruction::LD:
ld(instr);
break;
case Instruction::SC:
sc(instr);
break;
case Instruction::SWC1:
swc1(instr);
break;
case Instruction::SCD:
scd(instr);
break;
case Instruction::SDC1:
sdc1(instr);
break;
case Instruction::SD:
sd(instr);
break;
default:
DumpBlockCacheToDisk();
panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.opcode(), u32(instr), static_cast<u64>(regs.oldPC));
}
}
} // namespace n64
+102
View File
@@ -0,0 +1,102 @@
#pragma once
#include <Instruction.hpp>
namespace n64 {
static bool SpecialEndsBlock(const Instruction instr) {
switch (instr.special()) {
case Instruction::JR:
case Instruction::JALR:
case Instruction::SYSCALL:
case Instruction::BREAK:
case Instruction::TGE:
case Instruction::TGEU:
case Instruction::TLT:
case Instruction::TLTU:
case Instruction::TEQ:
case Instruction::TNE:
return true;
default:
return false;
}
}
static bool InstrEndsBlock(const Instruction instr) {
switch (instr.opcode()) {
case Instruction::SPECIAL:
return SpecialEndsBlock(instr);
case Instruction::REGIMM:
case Instruction::J:
case Instruction::JAL:
case Instruction::BEQ:
case Instruction::BNE:
case Instruction::BLEZ:
case Instruction::BGTZ:
return true;
default:
return false;
}
}
static bool IsBranchLikely(const Instruction instr) {
switch (instr.opcode()) {
case Instruction::BEQL:
case Instruction::BNEL:
case Instruction::BLEZL:
case Instruction::BGTZL:
return true;
case Instruction::REGIMM:
switch (instr.regimm()) {
case Instruction::BLTZL:
case Instruction::BGEZL:
case Instruction::BLTZALL:
case Instruction::BGEZALL:
return true;
default:
return false;
}
case Instruction::COP1:
{
if (instr.cop_rs() == 0x08) {
if (instr.cop_rt() == 2 || instr.cop_rt() == 3)
return true;
return false;
}
return false;
}
default:
return false;
}
}
#ifdef _WIN32
#define ARG1 rcx
#define ARG2 rdx
#define ARG3 r8
#define ARG4 r9
#define SCR1 rax
#define SCR2 rcx
#define SCR3 rdx
#define SCR4 r8
#define SCR5 r9
#define SCR6 r10
#define SCR7 r11
#else
#define ARG1 rdi
#define ARG2 rsi
#define ARG3 rdx
#define ARG4 rcx
#define ARG5 r8
#define ARG6 r9
#define SCR1 rax
#define SCR2 rdi
#define SCR3 rsi
#define SCR4 rdx
#define SCR5 rcx
#define SCR6 r8
#define SCR7 r9
#define SCR8 r10
#define SCR9 r11
#endif
} // namespace n64
File diff suppressed because it is too large Load Diff