[JIT]: Stuck in a loop right now, but implemented more instructions and fixed constant branches not actually restoring the program counter if they are not taken
This commit is contained in:
@@ -35,8 +35,7 @@ int JIT::Step() {
|
|||||||
/*regs.cop0.HandleTLBException(blockPC);
|
/*regs.cop0.HandleTLBException(blockPC);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
|
||||||
return 1;*/
|
return 1;*/
|
||||||
Util::panic(
|
Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016X})",
|
||||||
"[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016lX})",
|
|
||||||
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
|
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,12 +44,14 @@ int JIT::Step() {
|
|||||||
|
|
||||||
if (!blockCache[upperIndex].empty()) {
|
if (!blockCache[upperIndex].empty()) {
|
||||||
if (blockCache[upperIndex][lowerIndex]) {
|
if (blockCache[upperIndex][lowerIndex]) {
|
||||||
|
Util::trace("[JIT]: Executing already compiled block @ 0x{:016X}", blockPC);
|
||||||
return blockCache[upperIndex][lowerIndex]();
|
return blockCache[upperIndex][lowerIndex]();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blockCache[upperIndex].resize(kLowerSize);
|
blockCache[upperIndex].resize(kLowerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Util::trace("[JIT]: Compiling block @ 0x{:016X}", blockPC);
|
||||||
const auto block = code.getCurr<BlockFn>();
|
const auto block = code.getCurr<BlockFn>();
|
||||||
blockCache[upperIndex][lowerIndex] = block;
|
blockCache[upperIndex][lowerIndex] = block;
|
||||||
|
|
||||||
@@ -63,7 +64,6 @@ int JIT::Step() {
|
|||||||
bool branchWasLikely = false;
|
bool branchWasLikely = false;
|
||||||
bool blockEndsOnBranch = false;
|
bool blockEndsOnBranch = false;
|
||||||
|
|
||||||
// code.int3();
|
|
||||||
code.sub(code.rsp, 8);
|
code.sub(code.rsp, 8);
|
||||||
code.push(code.rbp);
|
code.push(code.rbp);
|
||||||
code.mov(code.rbp, reinterpret_cast<uintptr_t>(this)); // Load context pointer
|
code.mov(code.rbp, reinterpret_cast<uintptr_t>(this)); // Load context pointer
|
||||||
@@ -76,7 +76,7 @@ int JIT::Step() {
|
|||||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, blockPC);
|
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, blockPC);
|
||||||
return 1;*/
|
return 1;*/
|
||||||
|
|
||||||
Util::panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016lX})", blockPC);
|
Util::panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016X})", blockPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, blockPC, paddr)) {
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, blockPC, paddr)) {
|
||||||
@@ -84,7 +84,7 @@ int JIT::Step() {
|
|||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
|
||||||
return 1;*/
|
return 1;*/
|
||||||
Util::panic(
|
Util::panic(
|
||||||
"[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016lX})",
|
"[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016X})",
|
||||||
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
|
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,8 +127,8 @@ int JIT::Step() {
|
|||||||
code.add(code.rsp, 8);
|
code.add(code.rsp, 8);
|
||||||
code.ret();
|
code.ret();
|
||||||
code.setProtectModeRE();
|
code.setProtectModeRE();
|
||||||
const auto dump = code.getCode();
|
// const auto dump = code.getCode();
|
||||||
Util::WriteFileBinary(dump, code.getSize(), "jit.dump");
|
// Util::WriteFileBinary(dump, code.getSize(), "jit.dump");
|
||||||
// Util::panic("");
|
// Util::panic("");
|
||||||
return block();
|
return block();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ private:
|
|||||||
|
|
||||||
void SkipSlot();
|
void SkipSlot();
|
||||||
void SkipSlotConstant();
|
void SkipSlotConstant();
|
||||||
|
void BranchNotTaken();
|
||||||
void BranchTaken(s64 offs);
|
void BranchTaken(s64 offs);
|
||||||
void BranchTaken(const Xbyak::Reg64 &offs);
|
void BranchTaken(const Xbyak::Reg64 &offs);
|
||||||
void BranchAbsTaken(s64 addr);
|
void BranchAbsTaken(s64 addr);
|
||||||
@@ -185,17 +186,17 @@ private:
|
|||||||
void mthi(u32);
|
void mthi(u32);
|
||||||
void mtlo(u32);
|
void mtlo(u32);
|
||||||
void nor(u32);
|
void nor(u32);
|
||||||
void sb(u32) {}
|
void sb(u32) { Util::panic("[JIT] Implement sb!"); }
|
||||||
void sc(u32) {}
|
void sc(u32) { Util::panic("[JIT] Implement sc!"); }
|
||||||
void scd(u32) {}
|
void scd(u32) { Util::panic("[JIT] Implement scd!"); }
|
||||||
void sd(u32) {}
|
void sd(u32) { Util::panic("[JIT] Implement sd!"); }
|
||||||
void sdc1(u32) {}
|
void sdc1(u32) { Util::panic("[JIT] Implement sdc1!"); }
|
||||||
void sdl(u32) {}
|
void sdl(u32) { Util::panic("[JIT] Implement sdl!"); }
|
||||||
void sdr(u32) {}
|
void sdr(u32) { Util::panic("[JIT] Implement sdr!"); }
|
||||||
void sh(u32) {}
|
void sh(u32) { Util::panic("[JIT] Implement sh!"); }
|
||||||
void sw(u32);
|
void sw(u32);
|
||||||
void swl(u32) {}
|
void swl(u32) { Util::panic("[JIT] Implement swl!"); }
|
||||||
void swr(u32) {}
|
void swr(u32) { Util::panic("[JIT] Implement swr!"); }
|
||||||
void slti(u32);
|
void slti(u32);
|
||||||
void sltiu(u32);
|
void sltiu(u32);
|
||||||
void slt(u32);
|
void slt(u32);
|
||||||
@@ -204,12 +205,12 @@ private:
|
|||||||
void sllv(u32);
|
void sllv(u32);
|
||||||
void sub(u32);
|
void sub(u32);
|
||||||
void subu(u32);
|
void subu(u32);
|
||||||
void swc1(u32) {}
|
void swc1(u32) { Util::panic("[JIT] Implement swc1!"); }
|
||||||
void sra(u32);
|
void sra(u32);
|
||||||
void srav(u32);
|
void srav(u32);
|
||||||
void srl(u32);
|
void srl(u32);
|
||||||
void srlv(u32);
|
void srlv(u32);
|
||||||
void trap(bool) {}
|
void trap(bool) { Util::panic("[JIT] Implement trap!"); }
|
||||||
void or_(u32);
|
void or_(u32);
|
||||||
void ori(u32);
|
void ori(u32);
|
||||||
void xor_(u32);
|
void xor_(u32);
|
||||||
|
|||||||
@@ -38,12 +38,22 @@ static bool InstrEndsBlock(const u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool IsBranchLikely(const u32 instr) {
|
static bool IsBranchLikely(const u32 instr) {
|
||||||
switch (instr >> 26 & 0x1F) {
|
switch (instr >> 26 & 0x3F) {
|
||||||
case BEQL:
|
case BEQL:
|
||||||
case BNEL:
|
case BNEL:
|
||||||
case BLEZL:
|
case BLEZL:
|
||||||
case BGTZL:
|
case BGTZL:
|
||||||
return true;
|
return true;
|
||||||
|
case REGIMM:
|
||||||
|
switch (instr >> 16 & 0x1f) {
|
||||||
|
case BLTZL:
|
||||||
|
case BGEZL:
|
||||||
|
case BLTZALL:
|
||||||
|
case BGEZALL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
case COP1:
|
case COP1:
|
||||||
{
|
{
|
||||||
const u8 mask_sub = (instr >> 21) & 0x1F;
|
const u8 mask_sub = (instr >> 21) & 0x1F;
|
||||||
@@ -57,16 +67,8 @@ static bool IsBranchLikely(const u32 instr) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
switch (instr >> 16 & 0x1F) {
|
|
||||||
case BLTZL:
|
|
||||||
case BGEZL:
|
|
||||||
case BLTZALL:
|
|
||||||
case BGEZALL:
|
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -165,6 +165,11 @@ void JIT::BranchTaken(const s64 offs) {
|
|||||||
code.mov(REG(qword, pc), code.rax);
|
code.mov(REG(qword, pc), code.rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JIT::BranchNotTaken() {
|
||||||
|
code.mov(code.rax, blockPC);
|
||||||
|
code.mov(REG(qword, pc), code.rax);
|
||||||
|
}
|
||||||
|
|
||||||
void JIT::BranchTaken(const Xbyak::Reg64 &offs) {
|
void JIT::BranchTaken(const Xbyak::Reg64 &offs) {
|
||||||
code.add(offs, blockPC);
|
code.add(offs, blockPC);
|
||||||
code.mov(REG(qword, pc), offs);
|
code.mov(REG(qword, pc), offs);
|
||||||
@@ -181,8 +186,7 @@ void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), ad
|
|||||||
do { \
|
do { \
|
||||||
Xbyak::Label taken, not_taken; \
|
Xbyak::Label taken, not_taken; \
|
||||||
code.j##cond(taken); \
|
code.j##cond(taken); \
|
||||||
code.mov(code.rax, blockPC); \
|
BranchNotTaken(); \
|
||||||
code.mov(REG(qword, pc), code.rax); \
|
|
||||||
code.jmp(not_taken); \
|
code.jmp(not_taken); \
|
||||||
code.L(taken); \
|
code.L(taken); \
|
||||||
BranchTaken(offs); \
|
BranchTaken(offs); \
|
||||||
@@ -194,8 +198,7 @@ void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), ad
|
|||||||
do { \
|
do { \
|
||||||
Xbyak::Label taken, not_taken; \
|
Xbyak::Label taken, not_taken; \
|
||||||
code.j##cond(taken); \
|
code.j##cond(taken); \
|
||||||
code.mov(code.rax, blockPC); \
|
BranchNotTaken(); \
|
||||||
code.mov(REG(qword, pc), code.rax); \
|
|
||||||
code.jmp(not_taken); \
|
code.jmp(not_taken); \
|
||||||
code.L(taken); \
|
code.L(taken); \
|
||||||
BranchAbsTaken(addr); \
|
BranchAbsTaken(addr); \
|
||||||
@@ -217,7 +220,10 @@ void JIT::BranchAbsTaken(const Xbyak::Reg64 &addr) { code.mov(REG(qword, pc), ad
|
|||||||
void JIT::branch_constant(const bool cond, const s64 offset) {
|
void JIT::branch_constant(const bool cond, const s64 offset) {
|
||||||
if (cond) {
|
if (cond) {
|
||||||
BranchTaken(offset);
|
BranchTaken(offset);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BranchNotTaken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::branch_likely_constant(const bool cond, const s64 offset) {
|
void JIT::branch_likely_constant(const bool cond, const s64 offset) {
|
||||||
@@ -231,35 +237,46 @@ void JIT::branch_likely_constant(const bool cond, const s64 offset) {
|
|||||||
void JIT::branch_abs_constant(const bool cond, const s64 address) {
|
void JIT::branch_abs_constant(const bool cond, const s64 address) {
|
||||||
if (cond) {
|
if (cond) {
|
||||||
BranchAbsTaken(address);
|
BranchAbsTaken(address);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BranchNotTaken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::bfc0(u32 instr) {
|
void JIT::bfc0(u32 instr) {
|
||||||
const s16 imm = instr;
|
const s16 imm = instr;
|
||||||
const s64 offset = u64((s64)imm) << 2;
|
const s64 offset = u64((s64)imm) << 2;
|
||||||
const s64 address = regs.pc + offset;
|
const s64 address = blockPC + offset;
|
||||||
// branch(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address);
|
// code.mov(code.al, REG(byte, cop1.fcr31.compare));
|
||||||
|
// code.test(code.al, code.al);
|
||||||
|
// branch(address, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::blfc0(u32 instr) {
|
void JIT::blfc0(u32 instr) {
|
||||||
const s16 imm = instr;
|
const s16 imm = instr;
|
||||||
const s64 offset = u64((s64)imm) << 2;
|
const s64 offset = u64((s64)imm) << 2;
|
||||||
const s64 address = regs.pc + offset;
|
const s64 address = blockPC + offset;
|
||||||
// branch_likely(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address);
|
// code.mov(code.al, REG(byte, cop1.fcr31.compare));
|
||||||
|
// code.test(code.al, code.al);
|
||||||
|
// branch_likely(address, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::bfc1(u32 instr) {
|
void JIT::bfc1(u32 instr) {
|
||||||
const s16 imm = instr;
|
const s16 imm = instr;
|
||||||
const s64 offset = u64((s64)imm) << 2;
|
const s64 offset = u64((s64)imm) << 2;
|
||||||
const s64 address = regs.pc + offset;
|
const s64 address = blockPC + offset;
|
||||||
// branch(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address);
|
// code.mov(code.al, REG(byte, cop1.fcr31.compare));
|
||||||
|
// code.test(code.al, code.al);
|
||||||
|
// branch(address, nz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::blfc1(u32 instr) {
|
void JIT::blfc1(u32 instr) {
|
||||||
const s16 imm = instr;
|
const s16 imm = instr;
|
||||||
const s64 offset = u64((s64)imm) << 2;
|
const s64 offset = u64((s64)imm) << 2;
|
||||||
const s64 address = regs.pc + offset;
|
const s64 address = blockPC + offset;
|
||||||
// branch_likely(regs, EvaluateCondition(regs, cond, regs.cop1.fcr31.compare, 1), address);
|
// code.mov(code.al, REG(byte, cop1.fcr31.compare));
|
||||||
|
// code.test(code.al, code.al);
|
||||||
|
// branch_likely(address, nz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::bltz(const u32 instr) {
|
void JIT::bltz(const u32 instr) {
|
||||||
@@ -547,7 +564,7 @@ void JIT::dadd(u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.IsRegConstant(RS(instr))) {
|
if (regs.IsRegConstant(RS(instr))) {
|
||||||
auto rs = regs.Read<u64>(RS(instr));
|
auto rs = regs.Read<u64>(RS(instr));
|
||||||
regs.Read<u64>(RT(instr), code.rax);
|
regs.Read<u64>(RT(instr), code.rax);
|
||||||
code.add(code.rax, rs);
|
code.add(code.rax, rs);
|
||||||
@@ -555,7 +572,7 @@ void JIT::dadd(u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.IsRegConstant(RT(instr))) {
|
if (regs.IsRegConstant(RT(instr))) {
|
||||||
auto rt = regs.Read<u64>(RT(instr));
|
auto rt = regs.Read<u64>(RT(instr));
|
||||||
regs.Read<u64>(RS(instr), code.rax);
|
regs.Read<u64>(RS(instr), code.rax);
|
||||||
code.add(code.rax, rt);
|
code.add(code.rax, rt);
|
||||||
@@ -589,7 +606,7 @@ void JIT::daddi(u32 instr) {
|
|||||||
|
|
||||||
regs.Read<u64>(RS(instr), code.rax);
|
regs.Read<u64>(RS(instr), code.rax);
|
||||||
code.add(code.rax, imm);
|
code.add(code.rax, imm);
|
||||||
regs.Write(RT(instr), code.rax);
|
regs.Write<u64>(RT(instr), code.rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::daddiu(u32 instr) {
|
void JIT::daddiu(u32 instr) {
|
||||||
@@ -847,7 +864,7 @@ void JIT::dsubu(u32 instr) {
|
|||||||
|
|
||||||
void JIT::j(const u32 instr) {
|
void JIT::j(const u32 instr) {
|
||||||
const s32 target = (instr & 0x3ffffff) << 2;
|
const s32 target = (instr & 0x3ffffff) << 2;
|
||||||
const s64 oldPC = branchPC - 8;
|
const s64 oldPC = blockPC - 8;
|
||||||
const s64 address = (oldPC & ~0xfffffff) | target;
|
const s64 address = (oldPC & ~0xfffffff) | target;
|
||||||
branch_abs_constant(true, address);
|
branch_abs_constant(true, address);
|
||||||
}
|
}
|
||||||
@@ -882,8 +899,10 @@ void JIT::lbu(u32 instr) {
|
|||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||||
Util::panic("[JIT]: Unhandled TLBL exception in LBU!");
|
Util::panic("[JIT]: Unhandled TLBL exception in LBU!");
|
||||||
} else {
|
} else {
|
||||||
const u8 value = mem.Read<u8>(regs, paddr);
|
code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast<uintptr_t>(®s) - reinterpret_cast<uintptr_t>(this))]);
|
||||||
regs.Write(RT(instr), value);
|
code.mov(code.edx, paddr);
|
||||||
|
emitMemberFunctionCall(&Mem::Read<u8>, &mem);
|
||||||
|
regs.Write<u8>(RT(instr), code.rax);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant LBU!");
|
Util::panic("[JIT]: Implement non constant LBU!");
|
||||||
@@ -898,7 +917,10 @@ void JIT::lb(u32 instr) {
|
|||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||||
Util::panic("[JIT]: Unhandled TLBL exception in LB!");
|
Util::panic("[JIT]: Unhandled TLBL exception in LB!");
|
||||||
} else {
|
} else {
|
||||||
regs.Write(RT(instr), (s8)mem.Read<u8>(regs, paddr));
|
code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast<uintptr_t>(®s) - reinterpret_cast<uintptr_t>(this))]);
|
||||||
|
code.mov(code.edx, paddr);
|
||||||
|
emitMemberFunctionCall(&Mem::Read<u8>, &mem);
|
||||||
|
regs.Write<s8>(RT(instr), code.rax);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant LB!");
|
Util::panic("[JIT]: Implement non constant LB!");
|
||||||
@@ -921,8 +943,10 @@ void JIT::ld(u32 instr) {
|
|||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||||
Util::panic("[JIT]: Unhandled TLBL exception in LD!");
|
Util::panic("[JIT]: Unhandled TLBL exception in LD!");
|
||||||
} else {
|
} else {
|
||||||
const s64 value = mem.Read<u64>(regs, paddr);
|
code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast<uintptr_t>(®s) - reinterpret_cast<uintptr_t>(this))]);
|
||||||
regs.Write(RT(instr), value);
|
code.mov(code.edx, paddr);
|
||||||
|
emitMemberFunctionCall(&Mem::Read<u64>, &mem);
|
||||||
|
regs.Write<u64>(RT(instr), code.rax);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant LD!");
|
Util::panic("[JIT]: Implement non constant LD!");
|
||||||
@@ -956,6 +980,7 @@ void JIT::ldl(u32 instr) {
|
|||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||||
Util::panic("[JIT]: Unhandled TLBL exception in LDL!");
|
Util::panic("[JIT]: Unhandled TLBL exception in LDL!");
|
||||||
} else {
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement constant LDL!");
|
||||||
const s32 shift = 8 * ((address ^ 0) & 7);
|
const s32 shift = 8 * ((address ^ 0) & 7);
|
||||||
const u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
const u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||||
const u64 data = mem.Read<u64>(regs, paddr & ~7);
|
const u64 data = mem.Read<u64>(regs, paddr & ~7);
|
||||||
@@ -976,6 +1001,7 @@ void JIT::ldr(u32 instr) {
|
|||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||||
Util::panic("[JIT]: Unhandled TLBL exception in LDR!");
|
Util::panic("[JIT]: Unhandled TLBL exception in LDR!");
|
||||||
} else {
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement constant LDR!");
|
||||||
const s32 shift = 8 * ((address ^ 7) & 7);
|
const s32 shift = 8 * ((address ^ 7) & 7);
|
||||||
const u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
const u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||||
const u64 data = mem.Read<u64>(regs, paddr & ~7);
|
const u64 data = mem.Read<u64>(regs, paddr & ~7);
|
||||||
@@ -1016,15 +1042,16 @@ void JIT::lh(u32 instr) {
|
|||||||
Util::panic("[JIT]: Implement non constant LH!");
|
Util::panic("[JIT]: Implement non constant LH!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::lhu(u32) {}
|
void JIT::lhu(u32) { Util::panic("[JIT]: Implement LHU!"); }
|
||||||
|
|
||||||
void JIT::ll(u32) {}
|
void JIT::ll(u32) { Util::panic("[JIT]: Implement constant LL!"); }
|
||||||
|
|
||||||
void JIT::lld(u32) {}
|
void JIT::lld(u32) { Util::panic("[JIT]: Implement constant LLD!"); }
|
||||||
|
|
||||||
void JIT::lw(u32 instr) {
|
void JIT::lw(u32 instr) {
|
||||||
if (regs.IsRegConstant(RS(instr))) {
|
|
||||||
const s16 offset = instr;
|
const s16 offset = instr;
|
||||||
|
u32 paddr = 0;
|
||||||
|
if (regs.IsRegConstant(RS(instr))) {
|
||||||
const u64 address = regs.Read<s64>(RS(instr)) + offset;
|
const u64 address = regs.Read<s64>(RS(instr)) + offset;
|
||||||
if (check_address_error(0b11, address)) {
|
if (check_address_error(0b11, address)) {
|
||||||
// regs.cop0.HandleTLBException(address);
|
// regs.cop0.HandleTLBException(address);
|
||||||
@@ -1034,7 +1061,6 @@ void JIT::lw(u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 paddr = 0;
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) {
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) {
|
||||||
// regs.cop0.HandleTLBException(address);
|
// regs.cop0.HandleTLBException(address);
|
||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||||
@@ -1049,22 +1075,32 @@ void JIT::lw(u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Util::panic("[JIT]: Implement non constant LW!");
|
code.mov(code.esi, Cop0::LOAD);
|
||||||
|
regs.Read<s64>(RS(instr), code.rdx);
|
||||||
|
code.add(code.rdx, offset);
|
||||||
|
code.mov(code.rcx, reinterpret_cast<uintptr_t>(&paddr));
|
||||||
|
emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0);
|
||||||
|
|
||||||
|
code.mov(code.rsi, code.ptr[code.rbp + (reinterpret_cast<uintptr_t>(®s) - reinterpret_cast<uintptr_t>(this))]);
|
||||||
|
code.mov(code.edx, paddr);
|
||||||
|
emitMemberFunctionCall(&Mem::Read<u32>, &mem);
|
||||||
|
regs.Write<s32>(RT(instr), code.rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JIT::lwc1(u32) {}
|
void JIT::lwc1(u32) { Util::panic("[JIT]: Implement constant LWC1!"); }
|
||||||
|
|
||||||
void JIT::lwl(u32) {}
|
void JIT::lwl(u32) { Util::panic("[JIT]: Implement constant LWL!"); }
|
||||||
|
|
||||||
void JIT::lwu(u32) {}
|
void JIT::lwu(u32) { Util::panic("[JIT]: Implement constant LWU!"); }
|
||||||
|
|
||||||
void JIT::lwr(u32) {}
|
void JIT::lwr(u32) { Util::panic("[JIT]: Implement constant LWR!"); }
|
||||||
|
|
||||||
void JIT::mfhi(u32 instr) {
|
void JIT::mfhi(u32 instr) {
|
||||||
if (regs.hiIsConstant) {
|
if (regs.hiIsConstant) {
|
||||||
regs.Write(RD(instr), regs.hi);
|
regs.Write(RD(instr), regs.hi);
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant MFHI!");
|
code.mov(code.rax, REG(qword, hi));
|
||||||
|
regs.Write<s64>(RD(instr), code.rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1072,7 +1108,8 @@ void JIT::mflo(u32 instr) {
|
|||||||
if (regs.loIsConstant) {
|
if (regs.loIsConstant) {
|
||||||
regs.Write(RD(instr), regs.lo);
|
regs.Write(RD(instr), regs.lo);
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant MFLO!");
|
code.mov(code.rax, REG(qword, lo));
|
||||||
|
regs.Write<s64>(RD(instr), code.rax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1109,7 +1146,9 @@ void JIT::mthi(u32 instr) {
|
|||||||
regs.hi = regs.Read<s64>(RS(instr));
|
regs.hi = regs.Read<s64>(RS(instr));
|
||||||
regs.hiIsConstant = true;
|
regs.hiIsConstant = true;
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant MTHI!");
|
regs.Read<s64>(RS(instr), code.rax);
|
||||||
|
code.mov(REG(qword, hi), code.rax);
|
||||||
|
regs.hiIsConstant = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1118,7 +1157,9 @@ void JIT::mtlo(u32 instr) {
|
|||||||
regs.lo = regs.Read<s64>(RS(instr));
|
regs.lo = regs.Read<s64>(RS(instr));
|
||||||
regs.loIsConstant = true;
|
regs.loIsConstant = true;
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant MTLO!");
|
regs.Read<s64>(RS(instr), code.rax);
|
||||||
|
code.mov(REG(qword, lo), code.rax);
|
||||||
|
regs.loIsConstant = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1165,12 +1206,14 @@ void JIT::sltu(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sll(u32 instr) {
|
void JIT::sll(u32 instr) {
|
||||||
if (regs.IsRegConstant(RT(instr))) {
|
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
|
if (regs.IsRegConstant(RT(instr))) {
|
||||||
s32 result = regs.Read<s64>(RT(instr)) << sa;
|
s32 result = regs.Read<s64>(RT(instr)) << sa;
|
||||||
regs.Write(RD(instr), (s64)result);
|
regs.Write(RD(instr), (s64)result);
|
||||||
} else {
|
} else {
|
||||||
Util::panic("[JIT]: Implement non constant SLL!");
|
regs.Read<s64>(RT(instr), code.rax);
|
||||||
|
code.sal(code.rax, sa);
|
||||||
|
regs.Write<s32>(RD(instr), code.eax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1246,6 +1289,7 @@ void JIT::srl(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::sw(const u32 instr) {
|
void JIT::sw(const u32 instr) {
|
||||||
|
u32 physical;
|
||||||
if (regs.IsRegConstant(RS(instr), RT(instr))) {
|
if (regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
const s16 offset = instr;
|
const s16 offset = instr;
|
||||||
const u64 address = regs.Read<s64>(RS(instr)) + offset;
|
const u64 address = regs.Read<s64>(RS(instr)) + offset;
|
||||||
@@ -1256,7 +1300,6 @@ void JIT::sw(const u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 physical;
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) {
|
if (!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) {
|
||||||
// regs.cop0.HandleTLBException(address);
|
// regs.cop0.HandleTLBException(address);
|
||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
@@ -1281,7 +1324,6 @@ void JIT::sw(const u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 physical;
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) {
|
if (!regs.cop0.MapVAddr(Cop0::STORE, address, physical)) {
|
||||||
// regs.cop0.HandleTLBException(address);
|
// regs.cop0.HandleTLBException(address);
|
||||||
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
// regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
@@ -1303,7 +1345,6 @@ void JIT::sw(const u32 instr) {
|
|||||||
|
|
||||||
code.mov(code.esi, Cop0::STORE);
|
code.mov(code.esi, Cop0::STORE);
|
||||||
|
|
||||||
u32 physical;
|
|
||||||
code.mov(code.rcx, reinterpret_cast<uintptr_t>(&physical));
|
code.mov(code.rcx, reinterpret_cast<uintptr_t>(&physical));
|
||||||
emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0);
|
emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0);
|
||||||
|
|
||||||
@@ -1321,7 +1362,6 @@ void JIT::sw(const u32 instr) {
|
|||||||
|
|
||||||
code.mov(code.esi, Cop0::STORE);
|
code.mov(code.esi, Cop0::STORE);
|
||||||
|
|
||||||
u32 physical;
|
|
||||||
code.mov(code.rcx, reinterpret_cast<uintptr_t>(&physical));
|
code.mov(code.rcx, reinterpret_cast<uintptr_t>(&physical));
|
||||||
emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0);
|
emitMemberFunctionCall(&Cop0::MapVAddr, ®s.cop0);
|
||||||
|
|
||||||
@@ -1351,9 +1391,6 @@ void JIT::or_(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JIT::ori(u32 instr) {
|
void JIT::ori(u32 instr) {
|
||||||
if (RT(instr) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
s64 imm = (u16)instr;
|
s64 imm = (u16)instr;
|
||||||
if (regs.IsRegConstant(RS(instr))) {
|
if (regs.IsRegConstant(RS(instr))) {
|
||||||
s64 result = imm | regs.Read<s64>(RS(instr));
|
s64 result = imm | regs.Read<s64>(RS(instr));
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ void Cop0::decodeInterp(const u32 instr) {
|
|||||||
eret();
|
eret();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr,
|
Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016X})", mask_cop2 >> 3, mask_cop2 & 7, instr,
|
||||||
regs.oldPC);
|
regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ void Registers::Write<bool>(size_t idx, bool v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,13 +129,13 @@ void Registers::Write<u64>(size_t idx, u64 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void Registers::Write<s64>(size_t idx, s64 v) {
|
void Registers::Write<s64>(size_t idx, s64 v) {
|
||||||
Write<u64>(idx, v, isConstant);
|
Write<u64>(idx, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -143,7 +143,7 @@ void Registers::Write<u32>(size_t idx, u32 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ void Registers::Write<s32>(size_t idx, s32 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ void Registers::Write<u16>(size_t idx, u16 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ void Registers::Write<s16>(size_t idx, s16 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ void Registers::Write<u8>(size_t idx, u8 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ void Registers::Write<s8>(size_t idx, s8 v) {
|
|||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gprIsConstant[idx] = isConstant;
|
gprIsConstant[idx] = true;
|
||||||
gpr[idx] = v;
|
gpr[idx] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user