More progress on JIT constant instructions implementations
This commit is contained in:
@@ -23,7 +23,7 @@ void JIT::CheckCompareInterrupt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int JIT::Step() {
|
int JIT::Step() {
|
||||||
u32 instruction;
|
u32 instruction = 0;
|
||||||
s64 pc = regs.pc;
|
s64 pc = regs.pc;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -32,19 +32,23 @@ int JIT::Step() {
|
|||||||
// regs.prevDelaySlot = regs.delaySlot;
|
// regs.prevDelaySlot = regs.delaySlot;
|
||||||
// regs.delaySlot = false;
|
// regs.delaySlot = false;
|
||||||
|
|
||||||
/*if (check_address_error(0b11, u64(pc))) [[unlikely]] {
|
if (check_address_error(0b11, u64(pc))) [[unlikely]] {
|
||||||
regs.cop0.HandleTLBException(pc);
|
/*regs.cop0.HandleTLBException(pc);
|
||||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, pc);
|
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, pc);
|
||||||
return 1;
|
return 1;*/
|
||||||
}*/
|
|
||||||
|
Util::panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016lX})",
|
||||||
|
static_cast<u64>(regs.pc));
|
||||||
|
}
|
||||||
|
|
||||||
u32 paddr = 0;
|
u32 paddr = 0;
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, pc, paddr)) {
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, pc, paddr)) {
|
||||||
/*regs.cop0.HandleTLBException(pc);
|
/*regs.cop0.HandleTLBException(pc);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, pc);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, pc);
|
||||||
return 1;*/
|
return 1;*/
|
||||||
Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!",
|
Util::panic(
|
||||||
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)));
|
"[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>(regs.pc));
|
||||||
}
|
}
|
||||||
|
|
||||||
instruction = mem.Read<u32>(regs, paddr);
|
instruction = mem.Read<u32>(regs, paddr);
|
||||||
@@ -56,10 +60,12 @@ int JIT::Step() {
|
|||||||
|
|
||||||
pc += 4;
|
pc += 4;
|
||||||
|
|
||||||
// Exec(instruction);
|
Emit(instruction);
|
||||||
}
|
}
|
||||||
while (!InstrEndsBlock(instruction));
|
while (!InstrEndsBlock(instruction));
|
||||||
|
|
||||||
|
// emit code to store the value of pc
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,23 @@
|
|||||||
#include <BaseCPU.hpp>
|
#include <BaseCPU.hpp>
|
||||||
#include <Mem.hpp>
|
#include <Mem.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <xbyak.h>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Core;
|
struct Core;
|
||||||
|
|
||||||
|
static constexpr u32 kAddressSpaceSize = 0x8000'0000; // >> 20 = 0x800
|
||||||
|
static constexpr u32 kLowerSize = kAddressSpaceSize >> 20; // 0x800
|
||||||
|
static constexpr u32 kUpperSize = 1 << 20; // 0x100000
|
||||||
|
static constexpr u32 kCodeCacheSize = 32_mb;
|
||||||
|
static constexpr u32 kCodeCacheAllocSize = kCodeCacheSize + 4096;
|
||||||
|
|
||||||
|
struct CodeGenerator : Xbyak::CodeGenerator {
|
||||||
|
CodeGenerator() : Xbyak::CodeGenerator{kCodeCacheSize} {}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BranchCondition { EQ, NE, GT, GE, LT, LE, GTU, GEU, LTU, LEU };
|
||||||
|
|
||||||
struct JIT : BaseCPU {
|
struct JIT : BaseCPU {
|
||||||
explicit JIT(ParallelRDP &);
|
explicit JIT(ParallelRDP &);
|
||||||
~JIT() override = default;
|
~JIT() override = default;
|
||||||
@@ -23,19 +36,21 @@ struct JIT : BaseCPU {
|
|||||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32, u32) const override { return {}; }
|
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32, u32) const override { return {}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CodeGenerator code;
|
||||||
Registers regs;
|
Registers regs;
|
||||||
Mem mem;
|
Mem mem;
|
||||||
u64 cop2Latch{};
|
u64 cop2Latch{};
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
|
|
||||||
#define check_address_error(mask, vaddr) \
|
#define check_address_error(mask, vaddr) \
|
||||||
(((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
(((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
||||||
bool ShouldServiceInterrupt() const override;
|
|
||||||
|
[[nodiscard]] bool ShouldServiceInterrupt() const override;
|
||||||
void CheckCompareInterrupt() override;
|
void CheckCompareInterrupt() override;
|
||||||
std::vector<u8> Serialize() override;
|
std::vector<u8> Serialize() override;
|
||||||
void Deserialize(const std::vector<u8> &) override;
|
void Deserialize(const std::vector<u8> &) override;
|
||||||
|
|
||||||
void Emit(u32);
|
void Emit(u32);
|
||||||
void cop2Decode(u32);
|
|
||||||
void special(u32);
|
void special(u32);
|
||||||
void regimm(u32);
|
void regimm(u32);
|
||||||
void add(u32);
|
void add(u32);
|
||||||
@@ -44,12 +59,14 @@ private:
|
|||||||
void addiu(u32);
|
void addiu(u32);
|
||||||
void andi(u32);
|
void andi(u32);
|
||||||
void and_(u32);
|
void and_(u32);
|
||||||
void branch(bool, s64);
|
void b(u32 instr, BranchCondition, u32 reg1, u32 reg2);
|
||||||
void branch_likely(bool, s64);
|
void b(u32 instr, BranchCondition, u32 reg);
|
||||||
void b(u32, bool);
|
void blink(u32 instr, BranchCondition, u32 reg1, u32 reg2);
|
||||||
void blink(u32, bool);
|
void blink(u32 instr, BranchCondition, u32 reg);
|
||||||
void bl(u32, bool);
|
void bl(u32 instr, BranchCondition, u32 reg1, u32 reg2);
|
||||||
void bllink(u32, bool);
|
void bl(u32 instr, BranchCondition, u32 reg);
|
||||||
|
void bllink(u32 instr, BranchCondition, u32 reg1, u32 reg2);
|
||||||
|
void bllink(u32 instr, BranchCondition, u32 reg);
|
||||||
void dadd(u32);
|
void dadd(u32);
|
||||||
void daddu(u32);
|
void daddu(u32);
|
||||||
void daddi(u32);
|
void daddi(u32);
|
||||||
@@ -79,6 +96,7 @@ private:
|
|||||||
void lbu(u32);
|
void lbu(u32);
|
||||||
void lb(u32);
|
void lb(u32);
|
||||||
void ld(u32);
|
void ld(u32);
|
||||||
|
void ldc1(u32);
|
||||||
void ldl(u32);
|
void ldl(u32);
|
||||||
void ldr(u32);
|
void ldr(u32);
|
||||||
void lh(u32);
|
void lh(u32);
|
||||||
@@ -86,6 +104,7 @@ private:
|
|||||||
void ll(u32);
|
void ll(u32);
|
||||||
void lld(u32);
|
void lld(u32);
|
||||||
void lw(u32);
|
void lw(u32);
|
||||||
|
void lwc1(u32);
|
||||||
void lwl(u32);
|
void lwl(u32);
|
||||||
void lwu(u32);
|
void lwu(u32);
|
||||||
void lwr(u32);
|
void lwr(u32);
|
||||||
@@ -100,6 +119,7 @@ private:
|
|||||||
void sc(u32);
|
void sc(u32);
|
||||||
void scd(u32);
|
void scd(u32);
|
||||||
void sd(u32);
|
void sd(u32);
|
||||||
|
void sdc1(u32);
|
||||||
void sdl(u32);
|
void sdl(u32);
|
||||||
void sdr(u32);
|
void sdr(u32);
|
||||||
void sh(u32);
|
void sh(u32);
|
||||||
@@ -114,6 +134,7 @@ private:
|
|||||||
void sllv(u32);
|
void sllv(u32);
|
||||||
void sub(u32);
|
void sub(u32);
|
||||||
void subu(u32);
|
void subu(u32);
|
||||||
|
void swc1(u32);
|
||||||
void sra(u32);
|
void sra(u32);
|
||||||
void srav(u32);
|
void srav(u32);
|
||||||
void srl(u32);
|
void srl(u32);
|
||||||
@@ -123,12 +144,5 @@ private:
|
|||||||
void ori(u32);
|
void ori(u32);
|
||||||
void xor_(u32);
|
void xor_(u32);
|
||||||
void xori(u32);
|
void xori(u32);
|
||||||
|
|
||||||
void mtc2(u32);
|
|
||||||
void mfc2(u32);
|
|
||||||
void dmtc2(u32);
|
|
||||||
void dmfc2(u32);
|
|
||||||
void ctc2(u32);
|
|
||||||
void cfc2(u32);
|
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
388
src/backend/core/jit/decode.cpp
Normal file
388
src/backend/core/jit/decode.cpp
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
#include <JIT.hpp>
|
||||||
|
#include <CpuDefinitions.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
void JIT::special(const u32 instr) {
|
||||||
|
// 00rr_rccc
|
||||||
|
switch (const u8 mask = instr & 0x3F) {
|
||||||
|
case SLL:
|
||||||
|
if (instr != 0) {
|
||||||
|
sll(instr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SRL:
|
||||||
|
srl(instr);
|
||||||
|
break;
|
||||||
|
case SRA:
|
||||||
|
sra(instr);
|
||||||
|
break;
|
||||||
|
case SLLV:
|
||||||
|
sllv(instr);
|
||||||
|
break;
|
||||||
|
case SRLV:
|
||||||
|
srlv(instr);
|
||||||
|
break;
|
||||||
|
case SRAV:
|
||||||
|
srav(instr);
|
||||||
|
break;
|
||||||
|
case JR:
|
||||||
|
jr(instr);
|
||||||
|
break;
|
||||||
|
case JALR:
|
||||||
|
jalr(instr);
|
||||||
|
break;
|
||||||
|
case SYSCALL:
|
||||||
|
regs.cop0.FireException(ExceptionCode::Syscall, 0, regs.oldPC);
|
||||||
|
break;
|
||||||
|
case BREAK:
|
||||||
|
regs.cop0.FireException(ExceptionCode::Breakpoint, 0, regs.oldPC);
|
||||||
|
break;
|
||||||
|
case SYNC:
|
||||||
|
break; // SYNC
|
||||||
|
case MFHI:
|
||||||
|
mfhi(instr);
|
||||||
|
break;
|
||||||
|
case MTHI:
|
||||||
|
mthi(instr);
|
||||||
|
break;
|
||||||
|
case MFLO:
|
||||||
|
mflo(instr);
|
||||||
|
break;
|
||||||
|
case MTLO:
|
||||||
|
mtlo(instr);
|
||||||
|
break;
|
||||||
|
case DSLLV:
|
||||||
|
dsllv(instr);
|
||||||
|
break;
|
||||||
|
case DSRLV:
|
||||||
|
dsrlv(instr);
|
||||||
|
break;
|
||||||
|
case DSRAV:
|
||||||
|
dsrav(instr);
|
||||||
|
break;
|
||||||
|
case MULT:
|
||||||
|
mult(instr);
|
||||||
|
break;
|
||||||
|
case MULTU:
|
||||||
|
multu(instr);
|
||||||
|
break;
|
||||||
|
case DIV:
|
||||||
|
div(instr);
|
||||||
|
break;
|
||||||
|
case DIVU:
|
||||||
|
divu(instr);
|
||||||
|
break;
|
||||||
|
case DMULT:
|
||||||
|
dmult(instr);
|
||||||
|
break;
|
||||||
|
case DMULTU:
|
||||||
|
dmultu(instr);
|
||||||
|
break;
|
||||||
|
case DDIV:
|
||||||
|
ddiv(instr);
|
||||||
|
break;
|
||||||
|
case DDIVU:
|
||||||
|
ddivu(instr);
|
||||||
|
break;
|
||||||
|
case ADD:
|
||||||
|
add(instr);
|
||||||
|
break;
|
||||||
|
case ADDU:
|
||||||
|
addu(instr);
|
||||||
|
break;
|
||||||
|
case SUB:
|
||||||
|
sub(instr);
|
||||||
|
break;
|
||||||
|
case SUBU:
|
||||||
|
subu(instr);
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
and_(instr);
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
or_(instr);
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
xor_(instr);
|
||||||
|
break;
|
||||||
|
case NOR:
|
||||||
|
nor(instr);
|
||||||
|
break;
|
||||||
|
case SLT:
|
||||||
|
slt(instr);
|
||||||
|
break;
|
||||||
|
case SLTU:
|
||||||
|
sltu(instr);
|
||||||
|
break;
|
||||||
|
case DADD:
|
||||||
|
dadd(instr);
|
||||||
|
break;
|
||||||
|
case DADDU:
|
||||||
|
daddu(instr);
|
||||||
|
break;
|
||||||
|
case DSUB:
|
||||||
|
dsub(instr);
|
||||||
|
break;
|
||||||
|
case DSUBU:
|
||||||
|
dsubu(instr);
|
||||||
|
break;
|
||||||
|
case TGE:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) >= regs.Read<s64>(RT(instr)));
|
||||||
|
break;
|
||||||
|
case TGEU:
|
||||||
|
trap(regs.Read<u64>(RS(instr)) >= regs.Read<u64>(RT(instr)));
|
||||||
|
break;
|
||||||
|
case TLT:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) < regs.Read<s64>(RT(instr)));
|
||||||
|
break;
|
||||||
|
case TLTU:
|
||||||
|
trap(regs.Read<u64>(RS(instr)) < regs.Read<u64>(RT(instr)));
|
||||||
|
break;
|
||||||
|
case TEQ:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) == regs.Read<s64>(RT(instr)));
|
||||||
|
break;
|
||||||
|
case TNE:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) != regs.Read<s64>(RT(instr)));
|
||||||
|
break;
|
||||||
|
case DSLL:
|
||||||
|
dsll(instr);
|
||||||
|
break;
|
||||||
|
case DSRL:
|
||||||
|
dsrl(instr);
|
||||||
|
break;
|
||||||
|
case DSRA:
|
||||||
|
dsra(instr);
|
||||||
|
break;
|
||||||
|
case DSLL32:
|
||||||
|
dsll32(instr);
|
||||||
|
break;
|
||||||
|
case DSRL32:
|
||||||
|
dsrl32(instr);
|
||||||
|
break;
|
||||||
|
case DSRA32:
|
||||||
|
dsra32(instr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr,
|
||||||
|
static_cast<u64>(regs.oldPC));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::regimm(const u32 instr) {
|
||||||
|
// 000r_rccc
|
||||||
|
switch (const u8 mask = instr >> 16 & 0x1F) {
|
||||||
|
case BLTZ:
|
||||||
|
b(instr, LT, RS(instr));
|
||||||
|
break;
|
||||||
|
case BGEZ:
|
||||||
|
b(instr, GE, RS(instr));
|
||||||
|
break;
|
||||||
|
case BLTZL:
|
||||||
|
bl(instr, LT, RS(instr));
|
||||||
|
break;
|
||||||
|
case BGEZL:
|
||||||
|
bl(instr, GE, RS(instr));
|
||||||
|
break;
|
||||||
|
case TGEI:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) >= static_cast<s64>(static_cast<s16>(instr)));
|
||||||
|
break;
|
||||||
|
case TGEIU:
|
||||||
|
trap(regs.Read<u64>(RS(instr)) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
|
||||||
|
break;
|
||||||
|
case TLTI:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) < static_cast<s64>(static_cast<s16>(instr)));
|
||||||
|
break;
|
||||||
|
case TLTIU:
|
||||||
|
trap(regs.Read<u64>(RS(instr)) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
|
||||||
|
break;
|
||||||
|
case TEQI:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) == static_cast<s64>(static_cast<s16>(instr)));
|
||||||
|
break;
|
||||||
|
case TNEI:
|
||||||
|
trap(regs.Read<s64>(RS(instr)) != static_cast<s64>(static_cast<s16>(instr)));
|
||||||
|
break;
|
||||||
|
case BLTZAL:
|
||||||
|
blink(instr, LT, RS(instr));
|
||||||
|
break;
|
||||||
|
case BGEZAL:
|
||||||
|
blink(instr, GE, RS(instr));
|
||||||
|
break;
|
||||||
|
case BLTZALL:
|
||||||
|
bllink(instr, LT, RS(instr));
|
||||||
|
break;
|
||||||
|
case BGEZALL:
|
||||||
|
bllink(instr, GE, RS(instr));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr,
|
||||||
|
static_cast<u64>(regs.oldPC));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::Emit(const u32 instr) {
|
||||||
|
switch (const u8 mask = instr >> 26 & 0x3f) {
|
||||||
|
case SPECIAL:
|
||||||
|
special(instr);
|
||||||
|
break;
|
||||||
|
case REGIMM:
|
||||||
|
regimm(instr);
|
||||||
|
break;
|
||||||
|
case J:
|
||||||
|
j(instr);
|
||||||
|
break;
|
||||||
|
case JAL:
|
||||||
|
jal(instr);
|
||||||
|
break;
|
||||||
|
case BEQ:
|
||||||
|
b(instr, EQ, RS(instr), RT(instr));
|
||||||
|
break;
|
||||||
|
case BNE:
|
||||||
|
b(instr, NE, RS(instr), RT(instr));
|
||||||
|
break;
|
||||||
|
case BLEZ:
|
||||||
|
b(instr, LE, RS(instr));
|
||||||
|
break;
|
||||||
|
case BGTZ:
|
||||||
|
b(instr, GT, RS(instr));
|
||||||
|
break;
|
||||||
|
case ADDI:
|
||||||
|
addi(instr);
|
||||||
|
break;
|
||||||
|
case ADDIU:
|
||||||
|
addiu(instr);
|
||||||
|
break;
|
||||||
|
case SLTI:
|
||||||
|
slti(instr);
|
||||||
|
break;
|
||||||
|
case SLTIU:
|
||||||
|
sltiu(instr);
|
||||||
|
break;
|
||||||
|
case ANDI:
|
||||||
|
andi(instr);
|
||||||
|
break;
|
||||||
|
case ORI:
|
||||||
|
ori(instr);
|
||||||
|
break;
|
||||||
|
case XORI:
|
||||||
|
xori(instr);
|
||||||
|
break;
|
||||||
|
case LUI:
|
||||||
|
lui(instr);
|
||||||
|
break;
|
||||||
|
case COP0:
|
||||||
|
regs.cop0.decode(*this, instr);
|
||||||
|
break;
|
||||||
|
case COP1:
|
||||||
|
regs.cop1.decode(*this, instr);
|
||||||
|
break;
|
||||||
|
case COP2:
|
||||||
|
break;
|
||||||
|
case BEQL:
|
||||||
|
bl(instr, EQ, RS(instr), RT(instr));
|
||||||
|
break;
|
||||||
|
case BNEL:
|
||||||
|
bl(instr, NE, RS(instr), RT(instr));
|
||||||
|
break;
|
||||||
|
case BLEZL:
|
||||||
|
bl(instr, LE, RS(instr));
|
||||||
|
break;
|
||||||
|
case BGTZL:
|
||||||
|
bl(instr, GT, RS(instr));
|
||||||
|
break;
|
||||||
|
case DADDI:
|
||||||
|
daddi(instr);
|
||||||
|
break;
|
||||||
|
case DADDIU:
|
||||||
|
daddiu(instr);
|
||||||
|
break;
|
||||||
|
case LDL:
|
||||||
|
ldl(instr);
|
||||||
|
break;
|
||||||
|
case LDR:
|
||||||
|
ldr(instr);
|
||||||
|
break;
|
||||||
|
case 0x1F:
|
||||||
|
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||||
|
break;
|
||||||
|
case LB:
|
||||||
|
lb(instr);
|
||||||
|
break;
|
||||||
|
case LH:
|
||||||
|
lh(instr);
|
||||||
|
break;
|
||||||
|
case LWL:
|
||||||
|
lwl(instr);
|
||||||
|
break;
|
||||||
|
case LW:
|
||||||
|
lw(instr);
|
||||||
|
break;
|
||||||
|
case LBU:
|
||||||
|
lbu(instr);
|
||||||
|
break;
|
||||||
|
case LHU:
|
||||||
|
lhu(instr);
|
||||||
|
break;
|
||||||
|
case LWR:
|
||||||
|
lwr(instr);
|
||||||
|
break;
|
||||||
|
case LWU:
|
||||||
|
lwu(instr);
|
||||||
|
break;
|
||||||
|
case SB:
|
||||||
|
sb(instr);
|
||||||
|
break;
|
||||||
|
case SH:
|
||||||
|
sh(instr);
|
||||||
|
break;
|
||||||
|
case SWL:
|
||||||
|
swl(instr);
|
||||||
|
break;
|
||||||
|
case SW:
|
||||||
|
sw(instr);
|
||||||
|
break;
|
||||||
|
case SDL:
|
||||||
|
sdl(instr);
|
||||||
|
break;
|
||||||
|
case SDR:
|
||||||
|
sdr(instr);
|
||||||
|
break;
|
||||||
|
case SWR:
|
||||||
|
swr(instr);
|
||||||
|
break;
|
||||||
|
case CACHE:
|
||||||
|
break; // CACHE
|
||||||
|
case LL:
|
||||||
|
ll(instr);
|
||||||
|
break;
|
||||||
|
case LWC1:
|
||||||
|
lwc1(instr);
|
||||||
|
break;
|
||||||
|
case LLD:
|
||||||
|
lld(instr);
|
||||||
|
break;
|
||||||
|
case LDC1:
|
||||||
|
ldc1(instr);
|
||||||
|
break;
|
||||||
|
case LD:
|
||||||
|
ld(instr);
|
||||||
|
break;
|
||||||
|
case SC:
|
||||||
|
sc(instr);
|
||||||
|
break;
|
||||||
|
case SWC1:
|
||||||
|
swc1(instr);
|
||||||
|
break;
|
||||||
|
case SCD:
|
||||||
|
scd(instr);
|
||||||
|
break;
|
||||||
|
case SDC1:
|
||||||
|
sdc1(instr);
|
||||||
|
break;
|
||||||
|
case SD:
|
||||||
|
sd(instr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, static_cast<u64>(regs.oldPC));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace n64
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
#include <CpuDefinitions.hpp>
|
#include <CpuDefinitions.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
static inline bool SpecialEndsBlock(u32 instr) {
|
static bool SpecialEndsBlock(const u32 instr) {
|
||||||
u8 mask = instr & 0x3F;
|
switch (instr & 0x3F) {
|
||||||
switch (mask) {
|
|
||||||
case JR:
|
case JR:
|
||||||
case JALR:
|
case JALR:
|
||||||
case SYSCALL:
|
case SYSCALL:
|
||||||
@@ -20,9 +20,8 @@ static inline bool SpecialEndsBlock(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool InstrEndsBlock(u32 instr) {
|
static bool InstrEndsBlock(const u32 instr) {
|
||||||
u8 mask = (instr >> 26) & 0x3f;
|
switch (instr >> 26 & 0x3f) {
|
||||||
switch (mask) {
|
|
||||||
case SPECIAL:
|
case SPECIAL:
|
||||||
return SpecialEndsBlock(instr);
|
return SpecialEndsBlock(instr);
|
||||||
case REGIMM:
|
case REGIMM:
|
||||||
|
|||||||
@@ -79,6 +79,75 @@ void JIT::and_(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void branch(Registers ®s, const bool cond, const s64 address) {
|
||||||
|
regs.delaySlot = true;
|
||||||
|
if (cond) {
|
||||||
|
regs.nextPC = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void branch_likely(Registers ®s, const bool cond, const s64 address) {
|
||||||
|
if (cond) {
|
||||||
|
regs.delaySlot = true;
|
||||||
|
regs.nextPC = address;
|
||||||
|
} else {
|
||||||
|
regs.SetPC64(regs.nextPC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EvaluateCondition(Registers ®s, BranchCondition, u32, u32) {
|
||||||
|
Util::panic("[JIT]: non-constant EvaluateCondition!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EvaluateConditionConstant(Registers ®s, const BranchCondition cond, const u32 reg1, const u32 reg2) {
|
||||||
|
switch (cond) {
|
||||||
|
case EQ:
|
||||||
|
return regs.Read<s64>(reg1) == regs.Read<s64>(reg2);
|
||||||
|
case NE:
|
||||||
|
return regs.Read<s64>(reg1) != regs.Read<s64>(reg2);
|
||||||
|
case LT:
|
||||||
|
return regs.Read<s64>(reg1) < regs.Read<s64>(reg2);
|
||||||
|
case LE:
|
||||||
|
return regs.Read<s64>(reg1) <= regs.Read<s64>(reg2);
|
||||||
|
case GT:
|
||||||
|
return regs.Read<s64>(reg1) > regs.Read<s64>(reg2);
|
||||||
|
case GE:
|
||||||
|
return regs.Read<s64>(reg1) >= regs.Read<s64>(reg2);
|
||||||
|
case LTU:
|
||||||
|
return regs.Read<u64>(reg1) < regs.Read<u64>(reg2);
|
||||||
|
case LEU:
|
||||||
|
return regs.Read<u64>(reg1) <= regs.Read<u64>(reg2);
|
||||||
|
case GTU:
|
||||||
|
return regs.Read<u64>(reg1) > regs.Read<u64>(reg2);
|
||||||
|
case GEU:
|
||||||
|
return regs.Read<u64>(reg1) >= regs.Read<u64>(reg2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::b(u32 instr, BranchCondition cond, u32 reg1, u32 reg2) {
|
||||||
|
bool isConstant = regs.IsRegConstant(reg1, reg2);
|
||||||
|
if (isConstant) {
|
||||||
|
const s16 imm = instr;
|
||||||
|
const s64 offset = u64((s64)imm) << 2;
|
||||||
|
const s64 address = regs.pc + offset;
|
||||||
|
branch(regs, EvaluateConditionConstant(regs, cond, reg1, reg2), address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::b(u32 instr, BranchCondition cond, u32 reg) {}
|
||||||
|
|
||||||
|
void JIT::blink(u32 instr, BranchCondition cond, u32 reg1, u32 reg2) {}
|
||||||
|
|
||||||
|
void JIT::blink(u32 instr, BranchCondition cond, u32 reg) {}
|
||||||
|
|
||||||
|
void JIT::bl(u32 instr, BranchCondition cond, u32 reg1, u32 reg2) {}
|
||||||
|
|
||||||
|
void JIT::bl(u32 instr, BranchCondition cond, u32 reg) {}
|
||||||
|
|
||||||
|
void JIT::bllink(u32 instr, BranchCondition cond, u32 reg1, u32 reg2) {}
|
||||||
|
|
||||||
|
void JIT::bllink(u32 instr, BranchCondition cond, u32 reg) {}
|
||||||
|
|
||||||
void JIT::dadd(u32 instr) {
|
void JIT::dadd(u32 instr) {
|
||||||
if (regs.IsRegConstant(RS(instr), RT(instr))) {
|
if (regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
auto rs = regs.Read<u64>(RS(instr));
|
auto rs = regs.Read<u64>(RS(instr));
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ union FCR31 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CompConds { F, UN, EQ, UEQ, OLT, ULT, OLE, ULE, SF, NGLE, SEQ, NGL, LT, NGE, LE, NGT };
|
|
||||||
|
|
||||||
union FloatingPointReg {
|
union FloatingPointReg {
|
||||||
struct {
|
struct {
|
||||||
s32 int32;
|
s32 int32;
|
||||||
|
|||||||
Reference in New Issue
Block a user