structure jit
This commit is contained in:
@@ -57,6 +57,7 @@ add_subdirectory(src/backend)
|
|||||||
add_subdirectory(src/backend/netplay)
|
add_subdirectory(src/backend/netplay)
|
||||||
add_subdirectory(src/backend/core)
|
add_subdirectory(src/backend/core)
|
||||||
add_subdirectory(src/backend/core/interpreter)
|
add_subdirectory(src/backend/core/interpreter)
|
||||||
|
add_subdirectory(src/backend/core/JIT)
|
||||||
add_subdirectory(src/backend/core/mem)
|
add_subdirectory(src/backend/core/mem)
|
||||||
add_subdirectory(src/backend/core/mmio)
|
add_subdirectory(src/backend/core/mmio)
|
||||||
add_subdirectory(src/backend/core/registers)
|
add_subdirectory(src/backend/core/registers)
|
||||||
@@ -80,4 +81,4 @@ file(REMOVE
|
|||||||
${PROJECT_BINARY_DIR}/resources/shader.vert)
|
${PROJECT_BINARY_DIR}/resources/shader.vert)
|
||||||
|
|
||||||
target_link_libraries(kaizen PUBLIC frontend frontend-imgui
|
target_link_libraries(kaizen PUBLIC frontend frontend-imgui
|
||||||
discord-rpc imgui nfd parallel-rdp backend fmt::fmt mio::mio nlohmann_json::nlohmann_json core registers interpreter mem unarr mmio rsp SDL2::SDL2main SDL2::SDL2)
|
discord-rpc imgui nfd parallel-rdp backend fmt::fmt mio::mio nlohmann_json::nlohmann_json core registers jit interpreter mem unarr mmio rsp SDL2::SDL2main SDL2::SDL2)
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ struct JIT : BaseCPU, Xbyak::CodeGenerator {
|
|||||||
~JIT() override = default;
|
~JIT() override = default;
|
||||||
int Step() override;
|
int Step() override;
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
friend struct Cop1;
|
||||||
|
friend struct Cop0;
|
||||||
private:
|
private:
|
||||||
bool ShouldServiceInterrupt() override;
|
bool ShouldServiceInterrupt() override;
|
||||||
void CheckCompareInterrupt() override;
|
void CheckCompareInterrupt() override;
|
||||||
|
|||||||
4
src/backend/core/JIT/CMakeLists.txt
Normal file
4
src/backend/core/JIT/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
file(GLOB_RECURSE SOURCES *.cpp)
|
||||||
|
file(GLOB_RECURSE HEADERS *.hpp)
|
||||||
|
|
||||||
|
add_library(jit ${SOURCES} ${HEADERS})
|
||||||
@@ -130,8 +130,8 @@ void JIT::Emit(u32 instr) {
|
|||||||
case 0x0D: ori(instr); break;
|
case 0x0D: ori(instr); break;
|
||||||
case 0x0E: xori(instr); break;
|
case 0x0E: xori(instr); break;
|
||||||
case 0x0F: lui(instr); break;
|
case 0x0F: lui(instr); break;
|
||||||
case 0x10: regs.cop0.decode(regs, instr); break;
|
case 0x10: regs.cop0.decode(*this, instr); break;
|
||||||
case 0x11: regs.cop1.decode(regs, *this, instr); break;
|
case 0x11: regs.cop1.decode(*this, instr); break;
|
||||||
case 0x12: cop2Decode(instr); break;
|
case 0x12: cop2Decode(instr); break;
|
||||||
case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
||||||
|
|||||||
@@ -323,7 +323,22 @@ ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop0::decode(Registers& regs, u32 instr) {
|
template<class T>
|
||||||
|
void Cop0::decode(T& cpu, u32 instr) {
|
||||||
|
if constexpr (std::is_same_v<decltype(cpu), Interpreter>()) {
|
||||||
|
decodeInterpreter(cpu.regs, instr);
|
||||||
|
} else if constexpr (std::is_same_v<decltype(cpu), JIT>()) {
|
||||||
|
decodeJIT(cpu, instr);
|
||||||
|
} else {
|
||||||
|
Util::panic("What the fuck did you just give me?!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::decodeJIT(JIT& cpu, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::decodeInterp(Registers& regs, u32 instr) {
|
||||||
u8 mask_cop = (instr >> 21) & 0x1F;
|
u8 mask_cop = (instr >> 21) & 0x1F;
|
||||||
u8 mask_cop2 = instr & 0x3F;
|
u8 mask_cop2 = instr & 0x3F;
|
||||||
switch(mask_cop) {
|
switch(mask_cop) {
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ namespace n64 {
|
|||||||
#define ENTRY_HI_MASK 0xC00000FFFFFFE0FF
|
#define ENTRY_HI_MASK 0xC00000FFFFFFE0FF
|
||||||
#define PAGEMASK_MASK 0x1FFE000
|
#define PAGEMASK_MASK 0x1FFE000
|
||||||
|
|
||||||
struct Cpu;
|
struct JIT;
|
||||||
|
struct Interpreter;
|
||||||
struct Registers;
|
struct Registers;
|
||||||
struct Mem;
|
struct Mem;
|
||||||
|
|
||||||
@@ -235,7 +236,8 @@ struct Cop0 {
|
|||||||
TLBEntry tlb[32]{};
|
TLBEntry tlb[32]{};
|
||||||
TLBError tlbError = NONE;
|
TLBError tlbError = NONE;
|
||||||
s64 openbus{};
|
s64 openbus{};
|
||||||
void decode(Registers&, u32);
|
template <class T>
|
||||||
|
void decode(T&, u32);
|
||||||
FORCE_INLINE u32 GetRandom() {
|
FORCE_INLINE u32 GetRandom() {
|
||||||
int val = rand();
|
int val = rand();
|
||||||
int wired = GetWired();
|
int wired = GetWired();
|
||||||
@@ -255,11 +257,13 @@ private:
|
|||||||
FORCE_INLINE u32 GetWired() { return wired & 0x3F; }
|
FORCE_INLINE u32 GetWired() { return wired & 0x3F; }
|
||||||
FORCE_INLINE u32 GetCount() { return u32(u64(count >> 1)); }
|
FORCE_INLINE u32 GetCount() { return u32(u64(count >> 1)); }
|
||||||
|
|
||||||
void mtc0(n64::Registers&, u32);
|
void decodeInterp(Registers&, u32);
|
||||||
void dmtc0(n64::Registers&, u32);
|
void decodeJIT(JIT&, u32);
|
||||||
void mfc0(n64::Registers&, u32);
|
void mtc0(Registers&, u32);
|
||||||
void dmfc0(n64::Registers&, u32);
|
void dmtc0(Registers&, u32);
|
||||||
void eret(n64::Registers&);
|
void mfc0(Registers&, u32);
|
||||||
|
void dmfc0(Registers&, u32);
|
||||||
|
void eret(Registers&);
|
||||||
|
|
||||||
void tlbr();
|
void tlbr();
|
||||||
void tlbw(int);
|
void tlbw(int);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <core/registers/Cop1.hpp>
|
#include <core/registers/Cop1.hpp>
|
||||||
#include <core/registers/Registers.hpp>
|
#include <core/registers/Registers.hpp>
|
||||||
#include <core/Interpreter.hpp>
|
#include <core/Interpreter.hpp>
|
||||||
|
#include <core/JIT.hpp>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
@@ -14,7 +15,166 @@ void Cop1::Reset() {
|
|||||||
memset(fgr, 0, 32 * sizeof(FGR));
|
memset(fgr, 0, 32 * sizeof(FGR));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
template <class T>
|
||||||
|
void Cop1::decode(T& cpu, u32 instr) {
|
||||||
|
if constexpr (std::is_same_v<decltype(cpu), Interpreter>()) {
|
||||||
|
decodeInterp(cpu, instr);
|
||||||
|
} else if constexpr (std::is_same_v<decltype(cpu), JIT>()) {
|
||||||
|
decodeJIT(cpu, instr);
|
||||||
|
} else {
|
||||||
|
Util::panic("What the fuck did you just give me?!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::decodeInterp(Interpreter &cpu, u32 instr) {
|
||||||
|
Registers ®s = cpu.regs;
|
||||||
|
if(!regs.cop0.status.cu1) {
|
||||||
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 mask_sub = (instr >> 21) & 0x1F;
|
||||||
|
u8 mask_fun = instr & 0x3F;
|
||||||
|
u8 mask_branch = (instr >> 16) & 0x1F;
|
||||||
|
switch(mask_sub) {
|
||||||
|
// 000r_rccc
|
||||||
|
case 0x00: mfc1(regs, instr); break;
|
||||||
|
case 0x01: dmfc1(regs, instr); break;
|
||||||
|
case 0x02: cfc1(regs, instr); break;
|
||||||
|
case 0x03: FireException(regs, ExceptionCode::ReservedInstruction, 1, true); break;
|
||||||
|
case 0x04: mtc1(regs, instr); break;
|
||||||
|
case 0x05: dmtc1(regs, instr); break;
|
||||||
|
case 0x06: ctc1(regs, instr); break;
|
||||||
|
case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, true); break;
|
||||||
|
case 0x08:
|
||||||
|
switch(mask_branch) {
|
||||||
|
case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break;
|
||||||
|
case 1: cpu.b(instr, regs.cop1.fcr31.compare); break;
|
||||||
|
case 2: cpu.bl(instr, !regs.cop1.fcr31.compare); break;
|
||||||
|
case 3: cpu.bl(instr, regs.cop1.fcr31.compare); break;
|
||||||
|
default: Util::panic("Undefined BC COP1 {:02X}", mask_branch);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x10: // s
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x00: adds(regs, instr); break;
|
||||||
|
case 0x01: subs(regs, instr); break;
|
||||||
|
case 0x02: muls(regs, instr); break;
|
||||||
|
case 0x03: divs(regs, instr); break;
|
||||||
|
case 0x04: sqrts(regs, instr); break;
|
||||||
|
case 0x05: abss(regs, instr); break;
|
||||||
|
case 0x06: movs(regs, instr); break;
|
||||||
|
case 0x07: negs(regs, instr); break;
|
||||||
|
case 0x08: roundls(regs, instr); break;
|
||||||
|
case 0x09: truncls(regs, instr); break;
|
||||||
|
case 0x0A: ceills(regs, instr); break;
|
||||||
|
case 0x0B: floorls(regs, instr); break;
|
||||||
|
case 0x0C: roundws(regs, instr); break;
|
||||||
|
case 0x0D: truncws(regs, instr); break;
|
||||||
|
case 0x0E: ceilws(regs, instr); break;
|
||||||
|
case 0x0F: floorws(regs, instr); break;
|
||||||
|
case 0x20:
|
||||||
|
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
||||||
|
break;
|
||||||
|
case 0x21: cvtds(regs, instr); break;
|
||||||
|
case 0x24: cvtws(regs, instr); break;
|
||||||
|
case 0x25: cvtls(regs, instr); break;
|
||||||
|
case 0x30: ccond<float>(regs, instr, F); break;
|
||||||
|
case 0x31: ccond<float>(regs, instr, UN); break;
|
||||||
|
case 0x32: ccond<float>(regs, instr, EQ); break;
|
||||||
|
case 0x33: ccond<float>(regs, instr, UEQ); break;
|
||||||
|
case 0x34: ccond<float>(regs, instr, OLT); break;
|
||||||
|
case 0x35: ccond<float>(regs, instr, ULT); break;
|
||||||
|
case 0x36: ccond<float>(regs, instr, OLE); break;
|
||||||
|
case 0x37: ccond<float>(regs, instr, ULE); break;
|
||||||
|
case 0x38: ccond<float>(regs, instr, SF); break;
|
||||||
|
case 0x39: ccond<float>(regs, instr, NGLE); break;
|
||||||
|
case 0x3A: ccond<float>(regs, instr, SEQ); break;
|
||||||
|
case 0x3B: ccond<float>(regs, instr, NGL); break;
|
||||||
|
case 0x3C: ccond<float>(regs, instr, LT); break;
|
||||||
|
case 0x3D: ccond<float>(regs, instr, NGE); break;
|
||||||
|
case 0x3E: ccond<float>(regs, instr, LE); break;
|
||||||
|
case 0x3F: ccond<float>(regs, instr, NGT); break;
|
||||||
|
default: Util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x11: // d
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x00: addd(regs, instr); break;
|
||||||
|
case 0x01: subd(regs, instr); break;
|
||||||
|
case 0x02: muld(regs, instr); break;
|
||||||
|
case 0x03: divd(regs, instr); break;
|
||||||
|
case 0x04: sqrtd(regs, instr); break;
|
||||||
|
case 0x05: absd(regs, instr); break;
|
||||||
|
case 0x06: movd(regs, instr); break;
|
||||||
|
case 0x07: negd(regs, instr); break;
|
||||||
|
case 0x08: roundld(regs, instr); break;
|
||||||
|
case 0x09: truncld(regs, instr); break;
|
||||||
|
case 0x0A: ceilld(regs, instr); break;
|
||||||
|
case 0x0B: floorld(regs, instr); break;
|
||||||
|
case 0x0C: roundwd(regs, instr); break;
|
||||||
|
case 0x0D: truncwd(regs, instr); break;
|
||||||
|
case 0x0E: ceilwd(regs, instr); break;
|
||||||
|
case 0x0F: floorwd(regs, instr); break;
|
||||||
|
case 0x20: cvtsd(regs, instr); break;
|
||||||
|
case 0x21:
|
||||||
|
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
||||||
|
break;
|
||||||
|
case 0x24: cvtwd(regs, instr); break;
|
||||||
|
case 0x25: cvtld(regs, instr); break;
|
||||||
|
case 0x30: ccond<double>(regs, instr, F); break;
|
||||||
|
case 0x31: ccond<double>(regs, instr, UN); break;
|
||||||
|
case 0x32: ccond<double>(regs, instr, EQ); break;
|
||||||
|
case 0x33: ccond<double>(regs, instr, UEQ); break;
|
||||||
|
case 0x34: ccond<double>(regs, instr, OLT); break;
|
||||||
|
case 0x35: ccond<double>(regs, instr, ULT); break;
|
||||||
|
case 0x36: ccond<double>(regs, instr, OLE); break;
|
||||||
|
case 0x37: ccond<double>(regs, instr, ULE); break;
|
||||||
|
case 0x38: ccond<double>(regs, instr, SF); break;
|
||||||
|
case 0x39: ccond<double>(regs, instr, NGLE); break;
|
||||||
|
case 0x3A: ccond<double>(regs, instr, SEQ); break;
|
||||||
|
case 0x3B: ccond<double>(regs, instr, NGL); break;
|
||||||
|
case 0x3C: ccond<double>(regs, instr, LT); break;
|
||||||
|
case 0x3D: ccond<double>(regs, instr, NGE); break;
|
||||||
|
case 0x3E: ccond<double>(regs, instr, LE); break;
|
||||||
|
case 0x3F: ccond<double>(regs, instr, NGT); break;
|
||||||
|
default: Util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x14: // w
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x01: subw(regs, instr); break;
|
||||||
|
case 0x05: absw(regs, instr); break;
|
||||||
|
case 0x02: mulw(regs, instr); break;
|
||||||
|
case 0x06: movw(regs, instr); break;
|
||||||
|
case 0x20: cvtsw(regs, instr); break;
|
||||||
|
case 0x21: cvtdw(regs, instr); break;
|
||||||
|
case 0x24:
|
||||||
|
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
||||||
|
break;
|
||||||
|
default: Util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x15: // l
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x01: subl(regs, instr); break;
|
||||||
|
case 0x05: absl(regs, instr); break;
|
||||||
|
case 0x02: mull(regs, instr); break;
|
||||||
|
case 0x06: movl(regs, instr); break;
|
||||||
|
case 0x20: cvtsl(regs, instr); break;
|
||||||
|
case 0x21: cvtdl(regs, instr); break;
|
||||||
|
case 0x24: case 0x25:
|
||||||
|
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
||||||
|
break;
|
||||||
|
default: Util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: Util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::decodeJIT(JIT &cpu, u32 instr) {
|
||||||
|
Registers ®s = cpu.regs;
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ union FGR {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Interpreter;
|
struct Interpreter;
|
||||||
|
struct JIT;
|
||||||
struct Registers;
|
struct Registers;
|
||||||
|
|
||||||
struct Cop1 {
|
struct Cop1 {
|
||||||
@@ -65,8 +66,9 @@ struct Cop1 {
|
|||||||
FGR fgr[32]{};
|
FGR fgr[32]{};
|
||||||
void Reset();
|
void Reset();
|
||||||
template <class T> // either JIT or Interpreter
|
template <class T> // either JIT or Interpreter
|
||||||
void decode(Registers&, T&, u32);
|
void decode(T&, u32);
|
||||||
friend struct Interpreter;
|
friend struct Interpreter;
|
||||||
|
friend struct JIT;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE void SetReg(Cop0& cop0, u8 index, T value) {
|
FORCE_INLINE void SetReg(Cop0& cop0, u8 index, T value) {
|
||||||
@@ -136,8 +138,8 @@ struct Cop1 {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void decodeInterp(Registers&, Interpreter&, u32);
|
void decodeInterp(Interpreter&, u32);
|
||||||
void decodeJIT(Registers&, JIT&, u32);
|
void decodeJIT(JIT&, u32);
|
||||||
void absd(Registers&, u32 instr);
|
void absd(Registers&, u32 instr);
|
||||||
void abss(Registers&, u32 instr);
|
void abss(Registers&, u32 instr);
|
||||||
void absw(Registers&, u32 instr);
|
void absw(Registers&, u32 instr);
|
||||||
@@ -188,14 +190,27 @@ private:
|
|||||||
void negd(Registers&, u32 instr);
|
void negd(Registers&, u32 instr);
|
||||||
void sqrts(Registers&, u32 instr);
|
void sqrts(Registers&, u32 instr);
|
||||||
void sqrtd(Registers&, u32 instr);
|
void sqrtd(Registers&, u32 instr);
|
||||||
void lwc1(Registers&, Mem&, u32 instr);
|
template<class T>
|
||||||
void swc1(Registers&, Mem&, u32 instr);
|
void lwc1(T&, Mem&, u32);
|
||||||
void ldc1(Registers&, Mem&, u32 instr);
|
template<class T>
|
||||||
|
void swc1(T&, Mem&, u32);
|
||||||
|
template<class T>
|
||||||
|
void ldc1(T&, Mem&, u32);
|
||||||
|
template<class T>
|
||||||
|
void sdc1(T&, Mem&, u32);
|
||||||
|
|
||||||
|
void lwc1Interp(Registers&, Mem&, u32);
|
||||||
|
void swc1Interp(Registers&, Mem&, u32);
|
||||||
|
void ldc1Interp(Registers&, Mem&, u32);
|
||||||
|
void sdc1Interp(Registers&, Mem&, u32);
|
||||||
|
void lwc1JIT(JIT&, Mem&, u32);
|
||||||
|
void swc1JIT(JIT&, Mem&, u32);
|
||||||
|
void ldc1JIT(JIT&, Mem&, u32);
|
||||||
|
void sdc1JIT(JIT&, Mem&, u32);
|
||||||
void mfc1(Registers&, u32 instr);
|
void mfc1(Registers&, u32 instr);
|
||||||
void dmfc1(Registers&, u32 instr);
|
void dmfc1(Registers&, u32 instr);
|
||||||
void mtc1(Registers&, u32 instr);
|
void mtc1(Registers&, u32 instr);
|
||||||
void dmtc1(Registers&, u32 instr);
|
void dmtc1(Registers&, u32 instr);
|
||||||
void sdc1(Registers&, Mem&, u32 instr);
|
|
||||||
void truncws(Registers&, u32 instr);
|
void truncws(Registers&, u32 instr);
|
||||||
void truncwd(Registers&, u32 instr);
|
void truncwd(Registers&, u32 instr);
|
||||||
void truncls(Registers&, u32 instr);
|
void truncls(Registers&, u32 instr);
|
||||||
|
|||||||
@@ -443,7 +443,51 @@ void Cop1::floorwd(Registers& regs, u32 instr) {
|
|||||||
SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
|
SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) {
|
template<class T>
|
||||||
|
void Cop1::lwc1(T &cpu, Mem &mem, u32 instr) {
|
||||||
|
if constexpr(std::is_same_v<decltype(cpu), Interpreter>()) {
|
||||||
|
lwc1Interp(cpu.regs, mem, instr);
|
||||||
|
} else if(std::is_same_v<decltype(cpu), JIT>()) {
|
||||||
|
lwc1JIT(cpu, mem, instr);
|
||||||
|
} else {
|
||||||
|
Util::panic("What the fuck did you just give me?!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Cop1::swc1(T &cpu, Mem &mem, u32 instr) {
|
||||||
|
if constexpr(std::is_same_v<decltype(cpu), Interpreter>()) {
|
||||||
|
swc1Interp(cpu.regs, mem, instr);
|
||||||
|
} else if(std::is_same_v<decltype(cpu), JIT>()) {
|
||||||
|
swc1JIT(cpu, mem, instr);
|
||||||
|
} else {
|
||||||
|
Util::panic("What the fuck did you just give me?!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Cop1::ldc1(T &cpu, Mem &mem, u32 instr) {
|
||||||
|
if constexpr(std::is_same_v<decltype(cpu), Interpreter>()) {
|
||||||
|
ldc1Interp(cpu.regs, mem, instr);
|
||||||
|
} else if(std::is_same_v<decltype(cpu), JIT>()) {
|
||||||
|
ldc1JIT(cpu, mem, instr);
|
||||||
|
} else {
|
||||||
|
Util::panic("What the fuck did you just give me?!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Cop1::sdc1(T &cpu, Mem &mem, u32 instr) {
|
||||||
|
if constexpr(std::is_same_v<decltype(cpu), Interpreter>()) {
|
||||||
|
sdc1Interp(cpu.regs, mem, instr);
|
||||||
|
} else if(std::is_same_v<decltype(cpu), JIT>()) {
|
||||||
|
sdc1JIT(cpu, mem, instr);
|
||||||
|
} else {
|
||||||
|
Util::panic("What the fuck did you just give me?!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::lwc1Interp(Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
@@ -461,7 +505,7 @@ void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::swc1(Registers& regs, Mem& mem, u32 instr) {
|
void Cop1::swc1Interp(Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
@@ -478,7 +522,7 @@ void Cop1::swc1(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::ldc1(Registers& regs, Mem& mem, u32 instr) {
|
void Cop1::ldc1Interp(Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
@@ -496,7 +540,7 @@ void Cop1::ldc1(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::sdc1(Registers& regs, Mem& mem, u32 instr) {
|
void Cop1::sdc1Interp(Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user