Allocate only interpreter or dynarec + hopefully fixed some FPU bugs + hopefully it will build in Windows CI 🙏

This commit is contained in:
CocoSimone
2023-02-10 01:01:12 +01:00
parent ea5e4895ba
commit 6d58728239
24 changed files with 661 additions and 583 deletions

View File

@@ -12,10 +12,9 @@ add_library(imgui
imgui/backends/imgui_impl_vulkan.h imgui/backends/imgui_impl_vulkan.h
imgui/backends/imgui_impl_vulkan.cpp) imgui/backends/imgui_impl_vulkan.cpp)
if(WIN32) if(WIN32)
add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS) target_compile_definitions(imgui PUBLIC NOMINMAX _CRT_SECURE_NO_WARNINGS)
add_compile_options(/EHa) target_compile_options(imgui PUBLIC /EHa)
endif() endif()
target_include_directories(imgui PUBLIC ../parallel-rdp/parallel-rdp-standalone/volk target_include_directories(imgui PUBLIC ../parallel-rdp/parallel-rdp-standalone/volk

View File

@@ -44,6 +44,11 @@ add_library(parallel-rdp
parallel-rdp-standalone/volk/volk.c parallel-rdp-standalone/volk/volk.c
) )
if(WIN32)
target_compile_definitions(parallel-rdp PUBLIC NOMINMAX _CRT_SECURE_NO_WARNINGS)
target_compile_options(parallel-rdp PUBLIC /EHa)
endif()
target_compile_definitions(parallel-rdp PUBLIC GRANITE_VULKAN_MT) target_compile_definitions(parallel-rdp PUBLIC GRANITE_VULKAN_MT)
target_include_directories(parallel-rdp PUBLIC target_include_directories(parallel-rdp PUBLIC
@@ -55,11 +60,6 @@ target_include_directories(parallel-rdp PUBLIC
parallel-rdp-standalone/util parallel-rdp-standalone/util
) )
if(WIN32)
add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)
add_compile_options(/EHa)
endif()
if(WIN32) if(WIN32)
target_compile_definitions(parallel-rdp PUBLIC VK_USE_PLATFORM_WIN32_KHR) target_compile_definitions(parallel-rdp PUBLIC VK_USE_PLATFORM_WIN32_KHR)
else() else()

View File

@@ -76,8 +76,8 @@ else()
if(WIN32) if(WIN32)
target_compile_options(gadolinium PRIVATE /Od) target_compile_options(gadolinium PRIVATE /Od)
else() else()
target_compile_options(gadolinium PRIVATE -fsanitize=address) #target_compile_options(gadolinium PRIVATE -fsanitize=address)
target_link_options(gadolinium PRIVATE -fsanitize=address) #target_link_options(gadolinium PRIVATE -fsanitize=address)
target_compile_options(gadolinium PRIVATE -g) target_compile_options(gadolinium PRIVATE -g)
endif() endif()
endif() endif()

View File

@@ -25,7 +25,7 @@ CartInfo Core::LoadROM(const std::string& rom_) {
romLoaded = true; romLoaded = true;
CartInfo cartInfo = mem.LoadROM(rom); CartInfo cartInfo = mem.LoadROM(rom);
DoPIFHLE(mem, regs, cartInfo); DoPIFHLE(mem, CpuGetRegs(), cartInfo);
return cartInfo; return cartInfo;
} }
@@ -33,6 +33,7 @@ CartInfo Core::LoadROM(const std::string& rom_) {
void Core::Run(Window& window, float volumeL, float volumeR) { void Core::Run(Window& window, float volumeL, float volumeR) {
MMIO& mmio = mem.mmio; MMIO& mmio = mem.mmio;
Controller& controller = mmio.si.controller; Controller& controller = mmio.si.controller;
Registers& regs = CpuGetRegs();
for(int field = 0; field < mmio.vi.numFields; field++) { for(int field = 0; field < mmio.vi.numFields; field++) {
int frameCycles = 0; int frameCycles = 0;

View File

@@ -10,7 +10,7 @@ struct Window;
namespace n64 { namespace n64 {
enum class CpuType { enum class CpuType {
Dynarec, Interpreter Dynarec, Interpreter, NONE
}; };
struct Core { struct Core {
@@ -24,14 +24,27 @@ struct Core {
VI& GetVI() { return mem.mmio.vi; } VI& GetVI() { return mem.mmio.vi; }
void CpuReset() { void CpuReset() {
cpuDynarec.Reset(); switch(cpuType) {
regs.Reset(); case CpuType::Dynarec: cpuDynarec->Reset(); break;
case CpuType::Interpreter: cpuInterp->Reset(); break;
case CpuType::NONE: break;
}
}
Registers& CpuGetRegs() {
switch(cpuType) {
case CpuType::Dynarec: return cpuDynarec->regs;
case CpuType::Interpreter: return cpuInterp->regs;
case CpuType::NONE:
Util::panic("BRUH\n");
}
} }
int CpuStep() { int CpuStep() {
switch(cpuType) { switch(cpuType) {
case CpuType::Dynarec: return cpuDynarec.Step(mem, regs); case CpuType::Dynarec: return cpuDynarec->Step(mem);
case CpuType::Interpreter: cpuInterp.Step(mem, regs); return 1; case CpuType::Interpreter: cpuInterp->Step(mem); return 1;
case CpuType::NONE: return 0;
} }
} }
@@ -45,9 +58,8 @@ struct Core {
bool done = false; bool done = false;
std::string rom; std::string rom;
Mem mem; Mem mem;
CpuType cpuType = CpuType::Dynarec; CpuType cpuType = CpuType::NONE;
Interpreter cpuInterp; Interpreter* cpuInterp = nullptr;
JIT::Dynarec cpuDynarec; JIT::Dynarec* cpuDynarec = nullptr;
Registers regs;
}; };
} }

View File

@@ -6,7 +6,8 @@ namespace n64::JIT {
namespace fs = std::filesystem; namespace fs = std::filesystem;
Dynarec::~Dynarec() { Dynarec::~Dynarec() {
std::free(codeCache); Util::aligned_free(codeCache);
dump.close();
} }
Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) { Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) {
@@ -16,21 +17,47 @@ Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) {
CODECACHE_SIZE, CODECACHE_SIZE,
CodeArray::PROTECT_RWE CodeArray::PROTECT_RWE
); );
if(fs::exists("jit.dump")) {
fs::remove("jit.dump");
} }
void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) { dump.open("jit.dump", std::ios::ate | std::ios::binary);
dump.unsetf(std::ios::skipws);
}
inline bool ShouldServiceInterrupt(Registers& regs) {
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
bool interrupts_enabled = regs.cop0.status.ie == 1;
bool currently_handling_exception = regs.cop0.status.exl == 1;
bool currently_handling_error = regs.cop0.status.erl == 1;
return interrupts_pending && interrupts_enabled &&
!currently_handling_exception && !currently_handling_error;
}
inline void CheckCompareInterrupt(MI& mi, Registers& regs) {
regs.cop0.count++;
regs.cop0.count &= 0x1FFFFFFFF;
if(regs.cop0.count == (u64)regs.cop0.compare << 1) {
regs.cop0.cause.ip7 = 1;
UpdateInterrupt(mi, regs);
}
}
void Dynarec::Recompile(Mem& mem, u32 pc) {
bool branch = false, prevBranch = false; bool branch = false, prevBranch = false;
u32 startPC = pc; u32 startPC = pc;
u32 loopPC = pc; u32 loopPC = pc;
Fn block = code.getCurr<Fn>(); Fn block = code.getCurr<Fn>();
if(code.getSize() >= CODECACHE_SIZE) { if(code.getSize() >= CODECACHE_OVERHEAD) {
Util::print("Code cache overflow!\n"); Util::debug("Code cache overflow!\n");
code.setSize(code.getSize() & (CODECACHE_SIZE - 1)); code.setSize(0);
InvalidateCache(); InvalidateCache();
} }
Util::print("Start of block @ PC {:08X}\n", loopPC); Util::debug("Start of block @ PC {:08X}\n", loopPC);
code.sub(rsp, 8); code.sub(rsp, 8);
while(!prevBranch) { while(!prevBranch) {
@@ -38,9 +65,10 @@ void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) {
prevBranch = branch; prevBranch = branch;
u32 instr = mem.Read32<false>(regs, loopPC, loopPC); u32 instr = mem.Read32<false>(regs, loopPC, loopPC);
code.mov(rdi, (u64)&regs); emitBreakpoint();
code.mov(rdi, (uintptr_t)&regs);
Util::print("\tInstr: {:08X}, PC: {:08X}\n", instr, loopPC); Util::debug("\tInstr: {:08X}, PC: {:08X}\n", instr, loopPC);
code.mov(r8, qword[rdi + REG_OFFSET(oldPC)]); code.mov(r8, qword[rdi + REG_OFFSET(oldPC)]);
code.mov(r9, qword[rdi + REG_OFFSET(pc)]); code.mov(r9, qword[rdi + REG_OFFSET(pc)]);
code.mov(r10, qword[rdi + REG_OFFSET(nextPC)]); code.mov(r10, qword[rdi + REG_OFFSET(nextPC)]);
@@ -53,12 +81,13 @@ void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) {
loopPC += 4; loopPC += 4;
branch = Exec(regs, mem, instr); branch = Exec(mem, instr);
} }
code.add(rsp, 8); code.add(rsp, 8);
code.ret(); code.ret();
Util::print("End of block @ PC {:08X}, len: {}\n", loopPC, instrInBlock); Util::debug("End of block @ PC {:08X}, len: {}\n", loopPC, instrInBlock);
dump.write(code.getCode<char*>(), code.getSize());
blockCache[startPC >> 20][startPC & 0xFFF] = block; blockCache[startPC >> 20][startPC & 0xFFF] = block;
blockCache[startPC >> 20][startPC & 0xFFF](); blockCache[startPC >> 20][startPC & 0xFFF]();
@@ -68,7 +97,7 @@ void Dynarec::AllocateOuter(u32 pc) {
blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn)); blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn));
} }
int Dynarec::Step(Mem &mem, Registers& regs) { int Dynarec::Step(Mem &mem) {
instrInBlock = 0; instrInBlock = 0;
regs.gpr[0] = 0; regs.gpr[0] = 0;
regs.prevDelaySlot = regs.delaySlot; regs.prevDelaySlot = regs.delaySlot;
@@ -83,11 +112,17 @@ int Dynarec::Step(Mem &mem, Registers& regs) {
if(blockCache[pc >> 20][pc & 0xfff]) { if(blockCache[pc >> 20][pc & 0xfff]) {
blockCache[pc >> 20][pc & 0xfff](); blockCache[pc >> 20][pc & 0xfff]();
} else { } else {
Recompile(regs, mem, pc); Recompile(mem, pc);
} }
} else { } else {
AllocateOuter(pc); AllocateOuter(pc);
Recompile(regs, mem, pc); Recompile(mem, pc);
}
CheckCompareInterrupt(mem.mmio.mi, regs);
if(ShouldServiceInterrupt(regs)) {
FireException(regs, ExceptionCode::Interrupt, 0, false);
} }
return instrInBlock; return instrInBlock;

View File

@@ -2,6 +2,9 @@
#include <xbyak/xbyak.h> #include <xbyak/xbyak.h>
#include <backend/core/Mem.hpp> #include <backend/core/Mem.hpp>
#include <fstream> #include <fstream>
#include <Registers.hpp>
namespace n64 { struct Cop1; }
namespace n64::JIT { namespace n64::JIT {
using namespace Xbyak; using namespace Xbyak;
@@ -11,26 +14,30 @@ using Fn = void (*)();
#define GPR_OFFSET(x) ((uintptr_t)&regs.gpr[(x)] - (uintptr_t)&regs) #define GPR_OFFSET(x) ((uintptr_t)&regs.gpr[(x)] - (uintptr_t)&regs)
#define REG_OFFSET(kind) ((uintptr_t)&regs.kind - (uintptr_t)&regs) #define REG_OFFSET(kind) ((uintptr_t)&regs.kind - (uintptr_t)&regs)
#define CODECACHE_SIZE (2 << 25) #define CODECACHE_SIZE (2 << 25)
#define CODECACHE_OVERHEAD (CODECACHE_SIZE - 1_kb)
struct Dynarec { struct Dynarec {
Dynarec(); Dynarec();
~Dynarec(); ~Dynarec();
int Step(Mem&, n64::Registers&); int Step(Mem&);
void Reset() { void Reset() {
code.reset(); code.reset();
regs.Reset();
InvalidateCache(); InvalidateCache();
} }
u64 cop2Latch{}; u64 cop2Latch{};
CodeGenerator code; CodeGenerator code;
n64::Registers regs;
void InvalidatePage(u32); void InvalidatePage(u32);
void InvalidateCache(); void InvalidateCache();
private: private:
friend struct Cop1; friend struct n64::Cop1;
Fn* blockCache[0x80000]{}; Fn* blockCache[0x80000]{};
u8* codeCache; u8* codeCache;
int instrInBlock = 0; int instrInBlock = 0;
bool enableBreakpoints = false; bool enableBreakpoints = false;
u64 sizeUsed = 0; u64 sizeUsed = 0;
std::ofstream dump;
inline void emitBreakpoint() { inline void emitBreakpoint() {
#ifndef NDEBUG #ifndef NDEBUG
@@ -40,11 +47,11 @@ private:
} }
void* bumpAlloc(u64 size, u8 val = 0); void* bumpAlloc(u64 size, u8 val = 0);
void Recompile(n64::Registers&, Mem&, u32 pc); void Recompile(Mem&, u32 pc);
void AllocateOuter(u32 pc); void AllocateOuter(u32 pc);
void cop2Decode(n64::Registers&, u32); void cop2Decode(u32);
bool special(n64::Registers&, u32); bool special(u32);
bool regimm(n64::Registers&, u32); bool regimm(u32);
bool Exec(n64::Registers&, Mem&, u32); bool Exec(Mem&, u32);
}; };
} }

View File

@@ -21,7 +21,7 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) {
} }
} }
void Interpreter::Step(Mem& mem, Registers& regs) { void Interpreter::Step(Mem& mem) {
regs.gpr[0] = 0; regs.gpr[0] = 0;
CheckCompareInterrupt(mem.mmio.mi, regs); CheckCompareInterrupt(mem.mmio.mi, regs);
@@ -40,6 +40,6 @@ void Interpreter::Step(Mem& mem, Registers& regs) {
regs.pc = regs.nextPC; regs.pc = regs.nextPC;
regs.nextPC += 4; regs.nextPC += 4;
Exec(regs, mem, instruction); Exec(mem, instruction);
} }
} }

View File

@@ -7,106 +7,110 @@ namespace n64 {
struct Interpreter { struct Interpreter {
Interpreter() = default; Interpreter() = default;
~Interpreter() = default; ~Interpreter() = default;
void Step(Mem&, Registers&); void Step(Mem&);
void Reset() {
regs.Reset();
}
Registers regs;
private: private:
u64 cop2Latch{}; u64 cop2Latch{};
friend struct Cop1; friend struct Cop1;
void cop2Decode(Registers&, u32); void cop2Decode(u32);
void special(Registers&, u32); void special(u32);
void regimm(Registers&, u32); void regimm(u32);
void Exec(Registers&, Mem&, u32); void Exec(Mem&, u32);
void add(Registers&, u32); void add(u32);
void addu(Registers&, u32); void addu(u32);
void addi(Registers&, u32); void addi(u32);
void addiu(Registers&, u32); void addiu(u32);
void andi(Registers&, u32); void andi(u32);
void and_(Registers&, u32); void and_(u32);
void branch(Registers&, bool, s64); void branch(bool, s64);
void branch_likely(Registers&, bool, s64); void branch_likely(bool, s64);
void b(Registers&, u32, bool); void b(u32, bool);
void blink(Registers&, u32, bool); void blink(u32, bool);
void bl(Registers&, u32, bool); void bl(u32, bool);
void bllink(Registers&, u32, bool); void bllink(u32, bool);
void dadd(Registers&, u32); void dadd(u32);
void daddu(Registers&, u32); void daddu(u32);
void daddi(Registers&, u32); void daddi(u32);
void daddiu(Registers&, u32); void daddiu(u32);
void ddiv(Registers&, u32); void ddiv(u32);
void ddivu(Registers&, u32); void ddivu(u32);
void div(Registers&, u32); void div(u32);
void divu(Registers&, u32); void divu(u32);
void dmult(Registers&, u32); void dmult(u32);
void dmultu(Registers&, u32); void dmultu(u32);
void dsll(Registers&, u32); void dsll(u32);
void dsllv(Registers&, u32); void dsllv(u32);
void dsll32(Registers&, u32); void dsll32(u32);
void dsra(Registers&, u32); void dsra(u32);
void dsrav(Registers&, u32); void dsrav(u32);
void dsra32(Registers&, u32); void dsra32(u32);
void dsrl(Registers&, u32); void dsrl(u32);
void dsrlv(Registers&, u32); void dsrlv(u32);
void dsrl32(Registers&, u32); void dsrl32(u32);
void dsub(Registers&, u32); void dsub(u32);
void dsubu(Registers&, u32); void dsubu(u32);
void j(Registers&, u32); void j(u32);
void jr(Registers&, u32); void jr(u32);
void jal(Registers&, u32); void jal(u32);
void jalr(Registers&, u32); void jalr(u32);
void lui(Registers&, u32); void lui(u32);
void lbu(Registers&, Mem&, u32); void lbu(Mem&, u32);
void lb(Registers&, Mem&, u32); void lb(Mem&, u32);
void ld(Registers&, Mem&, u32); void ld(Mem&, u32);
void ldl(Registers&, Mem&, u32); void ldl(Mem&, u32);
void ldr(Registers&, Mem&, u32); void ldr(Mem&, u32);
void lh(Registers&, Mem&, u32); void lh(Mem&, u32);
void lhu(Registers&, Mem&, u32); void lhu(Mem&, u32);
void ll(Registers&, Mem&, u32); void ll(Mem&, u32);
void lld(Registers&, Mem&, u32); void lld(Mem&, u32);
void lw(Registers&, Mem&, u32); void lw(Mem&, u32);
void lwl(Registers&, Mem&, u32); void lwl(Mem&, u32);
void lwu(Registers&, Mem&, u32); void lwu(Mem&, u32);
void lwr(Registers&, Mem&, u32); void lwr(Mem&, u32);
void mfhi(Registers&, u32); void mfhi(u32);
void mflo(Registers&, u32); void mflo(u32);
void mult(Registers&, u32); void mult(u32);
void multu(Registers&, u32); void multu(u32);
void mthi(Registers&, u32); void mthi(u32);
void mtlo(Registers&, u32); void mtlo(u32);
void nor(Registers&, u32); void nor(u32);
void sb(Registers&, Mem&, u32); void sb(Mem&, u32);
void sc(Registers&, Mem&, u32); void sc(Mem&, u32);
void scd(Registers&, Mem&, u32); void scd(Mem&, u32);
void sd(Registers&, Mem&, u32); void sd(Mem&, u32);
void sdl(Registers&, Mem&, u32); void sdl(Mem&, u32);
void sdr(Registers&, Mem&, u32); void sdr(Mem&, u32);
void sh(Registers&, Mem&, u32); void sh(Mem&, u32);
void sw(Registers&, Mem&, u32); void sw(Mem&, u32);
void swl(Registers&, Mem&, u32); void swl(Mem&, u32);
void swr(Registers&, Mem&, u32); void swr(Mem&, u32);
void slti(Registers&, u32); void slti(u32);
void sltiu(Registers&, u32); void sltiu(u32);
void slt(Registers&, u32); void slt(u32);
void sltu(Registers&, u32); void sltu(u32);
void sll(Registers&, u32); void sll(u32);
void sllv(Registers&, u32); void sllv(u32);
void sub(Registers&, u32); void sub(u32);
void subu(Registers&, u32); void subu(u32);
void sra(Registers&, u32); void sra(u32);
void srav(Registers&, u32); void srav(u32);
void srl(Registers&, u32); void srl(u32);
void srlv(Registers&, u32); void srlv(u32);
void trap(Registers&, bool); void trap(bool);
void or_(Registers&, u32); void or_(u32);
void ori(Registers&, u32); void ori(u32);
void xor_(Registers&, u32); void xor_(u32);
void xori(Registers&, u32); void xori(u32);
void mtc2(Registers&, u32); void mtc2(u32);
void mfc2(Registers&, u32); void mfc2(u32);
void dmtc2(Registers&, u32); void dmtc2(u32);
void dmfc2(Registers&, u32); void dmfc2(u32);
void ctc2(Registers&, u32); void ctc2(u32);
void cfc2(Registers&, u32); void cfc2(u32);
}; };
} }

View File

@@ -281,6 +281,7 @@ struct RSP {
void ssv(u32 instr); void ssv(u32 instr);
void suv(u32 instr); void suv(u32 instr);
void slv(u32 instr); void slv(u32 instr);
void sfv(u32 instr);
void spv(u32 instr); void spv(u32 instr);
void sllv(u32 instr); void sllv(u32 instr);
void srlv(u32 instr); void srlv(u32 instr);

View File

@@ -21,7 +21,7 @@ void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
break; break;
case 0x04: case 0x04:
code.mov(code.rsi, (u64)instr); code.mov(code.rsi, (u64)instr);
code.mov(code.rax, (u64)mtc0); code.mov(code.rax, (uintptr_t)mtc0);
code.call(code.rax); code.call(code.rax);
break; break;
case 0x05: case 0x05:

View File

@@ -1,5 +1,6 @@
#include <dynarec/cop/cop1instructions.hpp> #include <dynarec/cop/cop1instructions.hpp>
#include <cfenv> #include <cfenv>
#include <cmath>
#include <Cop1.hpp> #include <Cop1.hpp>
#include <Registers.hpp> #include <Registers.hpp>
@@ -19,65 +20,39 @@ inline int PushRoundingMode(const FCR31& fcr31) {
#define PUSHROUNDINGMODE int og = PushRoundingMode(regs.cop1.fcr31) #define PUSHROUNDINGMODE int og = PushRoundingMode(regs.cop1.fcr31)
#define POPROUNDINGMODE fesetround(og) #define POPROUNDINGMODE fesetround(og)
#ifdef _WIN32 #define checknanregs(fs, ft) do { \
#define isnanf isnan if(std::isnan(fs) || std::isnan(ft)) { \
#define checknanregsf(fs, ft) \
if(isnanf(fs) || isnanf(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \ regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \ regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \ return; \
} } \
} while(0)
#define checknanregsd(fs, ft) \
if(isnan(fs) || isnan(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \
}
#else
#define checknanregsf(fs, ft) \
if(isnanf(fs) || isnanf(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \
}
#define checknanregsd(fs, ft) \
if(isnan(fs) || isnan(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \
}
#endif
void absd(n64::Registers& regs, u32 instr) { void absd(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fabs(fs)); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), std::abs(fs));
} }
void abss(n64::Registers& regs, u32 instr) { void abss(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fabsf(fs)); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), std::abs(fs));
} }
void absw(n64::Registers& regs, u32 instr) { void absw(n64::Registers& regs, u32 instr) {
s32 fs = regs.cop1.GetReg<s32>(regs.cop0, FS(instr)); s32 fs = regs.cop1.GetReg<s32>(regs.cop0, FS(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), abs(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), std::abs(fs));
} }
void absl(n64::Registers& regs, u32 instr) { void absl(n64::Registers& regs, u32 instr) {
s64 fs = regs.cop1.GetReg<s64>(regs.cop0, FS(instr)); s64 fs = regs.cop1.GetReg<s64>(regs.cop0, FS(instr));
regs.cop1.SetReg(regs.cop0, FD(instr), labs(fs)); regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs));
} }
void adds(n64::Registers& regs, u32 instr) { void adds(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr)); float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr));
checknanregsf(fs, ft) checknanregs(fs, ft);
float result = fs + ft; float result = fs + ft;
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), result); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), result);
} }
@@ -85,32 +60,32 @@ void adds(n64::Registers& regs, u32 instr) {
void addd(n64::Registers& regs, u32 instr) { void addd(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr)); double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr));
checknanregsf(fs, ft) checknanregs(fs, ft);
double result = fs + ft; double result = fs + ft;
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), result); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), result);
} }
void ceills(n64::Registers& regs, u32 instr) { void ceills(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s64 result = ceilf(fs); s64 result = std::ceil(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void ceilws(n64::Registers& regs, u32 instr) { void ceilws(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s32 result = ceilf(fs); s32 result = std::ceil(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void ceilld(n64::Registers& regs, u32 instr) { void ceilld(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s64 result = ceil(fs); s64 result = std::ceil(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void ceilwd(n64::Registers& regs, u32 instr) { void ceilwd(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s32 result = ceil(fs); s32 result = std::ceil(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
@@ -410,60 +385,60 @@ void negd(Registers &regs, u32 instr) {
void sqrts(Registers &regs, u32 instr) { void sqrts(Registers &regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), sqrtf(fs)); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), std::sqrt(fs));
} }
void sqrtd(Registers &regs, u32 instr) { void sqrtd(Registers &regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), sqrt(fs)); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), std::sqrt(fs));
} }
void roundls(n64::Registers& regs, u32 instr) { void roundls(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s32)nearbyintf(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void roundld(n64::Registers& regs, u32 instr) { void roundld(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)nearbyint(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void roundws(n64::Registers& regs, u32 instr) { void roundws(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)nearbyintf(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void roundwd(n64::Registers& regs, u32 instr) { void roundwd(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)nearbyint(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void floorls(n64::Registers& regs, u32 instr) { void floorls(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)floorf(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void floorld(n64::Registers& regs, u32 instr) { void floorld(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)floor(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void floorws(n64::Registers& regs, u32 instr) { void floorws(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)floorf(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void floorwd(n64::Registers& regs, u32 instr) { void floorwd(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)floor(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void lwc1(n64::Registers& regs, Mem& mem, u32 instr) { void lwc1(n64::Registers& regs, Mem& mem, u32 instr) {
@@ -550,25 +525,25 @@ void sdc1(n64::Registers& regs, Mem& mem, u32 instr) {
void truncws(n64::Registers& regs, u32 instr) { void truncws(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s32 result = (s32)truncf(fs); s32 result = (s32)std::trunc(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void truncwd(n64::Registers& regs, u32 instr) { void truncwd(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s32 result = (s32)trunc(fs); s32 result = (s32)std::trunc(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void truncls(n64::Registers& regs, u32 instr) { void truncls(n64::Registers& regs, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s64 result = (s64)truncf(fs); s64 result = (s64)std::trunc(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void truncld(n64::Registers& regs, u32 instr) { void truncld(n64::Registers& regs, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s64 result = (s64)trunc(fs); s64 result = (s64)std::trunc(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }

View File

@@ -4,10 +4,10 @@
#include <Registers.hpp> #include <Registers.hpp>
namespace n64::JIT { namespace n64::JIT {
void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) { void Dynarec::cop2Decode(u32 instr) {
code.mov(rdi, (u64)this); code.mov(rdi, (u64)this);
code.mov(rsi, (u64)&regs); code.mov(rsi, (u64)&regs);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
switch(RS(instr)) { switch(RS(instr)) {
case 0x00: case 0x00:
@@ -32,7 +32,7 @@ void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) {
} }
} }
bool Dynarec::special(n64::Registers& regs, u32 instr) { bool Dynarec::special(u32 instr) {
u8 mask = (instr & 0x3F); u8 mask = (instr & 0x3F);
bool res = false; bool res = false;
@@ -40,44 +40,44 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) {
switch (mask) { // TODO: named constants for clearer code switch (mask) { // TODO: named constants for clearer code
case 0: case 0:
if (instr != 0) { if (instr != 0) {
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)sll); code.mov(rax, (u64)sll);
code.call(rax); code.call(rax);
} }
break; break;
case 0x02: case 0x02:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)srl); code.mov(rax, (u64)srl);
code.call(rax); code.call(rax);
break; break;
case 0x03: case 0x03:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)sra); code.mov(rax, (u64)sra);
code.call(rax); code.call(rax);
break; break;
case 0x04: case 0x04:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)sllv); code.mov(rax, (u64)sllv);
code.call(rax); code.call(rax);
break; break;
case 0x06: case 0x06:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)srlv); code.mov(rax, (u64)srlv);
code.call(rax); code.call(rax);
break; break;
case 0x07: case 0x07:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)srav); code.mov(rax, (u64)srav);
code.call(rax); code.call(rax);
break; break;
case 0x08: case 0x08:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)jr); code.mov(rax, (u64)jr);
code.call(rax); code.call(rax);
res = true; res = true;
break; break;
case 0x09: case 0x09:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)jalr); code.mov(rax, (u64)jalr);
code.call(rax); code.call(rax);
res = true; res = true;
@@ -86,147 +86,147 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) {
case 0x0D: Util::panic("[RECOMPILER] Unhandled break instruction {:016X}\n", (u64)regs.pc); case 0x0D: Util::panic("[RECOMPILER] Unhandled break instruction {:016X}\n", (u64)regs.pc);
case 0x0F: break; // SYNC case 0x0F: break; // SYNC
case 0x10: case 0x10:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)mfhi); code.mov(rax, (u64)mfhi);
code.call(rax); code.call(rax);
break; break;
case 0x11: case 0x11:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)mthi); code.mov(rax, (u64)mthi);
code.call(rax); code.call(rax);
break; break;
case 0x12: case 0x12:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)mflo); code.mov(rax, (u64)mflo);
code.call(rax); code.call(rax);
break; break;
case 0x13: case 0x13:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)mtlo); code.mov(rax, (u64)mtlo);
code.call(rax); code.call(rax);
break; break;
case 0x14: case 0x14:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsllv); code.mov(rax, (u64)dsllv);
code.call(rax); code.call(rax);
break; break;
case 0x16: case 0x16:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsrlv); code.mov(rax, (u64)dsrlv);
code.call(rax); code.call(rax);
break; break;
case 0x17: case 0x17:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsrav); code.mov(rax, (u64)dsrav);
code.call(rax); code.call(rax);
break; break;
case 0x18: case 0x18:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)mult); code.mov(rax, (u64)mult);
code.call(rax); code.call(rax);
break; break;
case 0x19: case 0x19:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)multu); code.mov(rax, (u64)multu);
code.call(rax); code.call(rax);
break; break;
case 0x1A: case 0x1A:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)div); code.mov(rax, (u64)div);
code.call(rax); code.call(rax);
break; break;
case 0x1B: case 0x1B:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)divu); code.mov(rax, (u64)divu);
code.call(rax); code.call(rax);
break; break;
case 0x1C: case 0x1C:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dmult); code.mov(rax, (u64)dmult);
code.call(rax); code.call(rax);
break; break;
case 0x1D: case 0x1D:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dmultu); code.mov(rax, (u64)dmultu);
code.call(rax); code.call(rax);
break; break;
case 0x1E: case 0x1E:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)ddiv); code.mov(rax, (u64)ddiv);
code.call(rax); code.call(rax);
break; break;
case 0x1F: case 0x1F:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)ddivu); code.mov(rax, (u64)ddivu);
code.call(rax); code.call(rax);
break; break;
case 0x20: case 0x20:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)add); code.mov(rax, (u64)add);
code.call(rax); code.call(rax);
break; break;
case 0x21: case 0x21:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)addu); code.mov(rax, (u64)addu);
code.call(rax); code.call(rax);
break; break;
case 0x22: case 0x22:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)sub); code.mov(rax, (u64)sub);
code.call(rax); code.call(rax);
break; break;
case 0x23: case 0x23:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)subu); code.mov(rax, (u64)subu);
code.call(rax); code.call(rax);
break; break;
case 0x24: case 0x24:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)and_); code.mov(rax, (u64)and_);
code.call(rax); code.call(rax);
break; break;
case 0x25: case 0x25:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)or_); code.mov(rax, (u64)or_);
code.call(rax); code.call(rax);
break; break;
case 0x26: case 0x26:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)xor_); code.mov(rax, (u64)xor_);
code.call(rax); code.call(rax);
break; break;
case 0x27: case 0x27:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)nor); code.mov(rax, (u64)nor);
code.call(rax); code.call(rax);
break; break;
case 0x2A: case 0x2A:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)slt); code.mov(rax, (u64)slt);
code.call(rax); code.call(rax);
break; break;
case 0x2B: case 0x2B:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)sltu); code.mov(rax, (u64)sltu);
code.call(rax); code.call(rax);
break; break;
case 0x2C: case 0x2C:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dadd); code.mov(rax, (u64)dadd);
code.call(rax); code.call(rax);
break; break;
case 0x2D: case 0x2D:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)daddu); code.mov(rax, (u64)daddu);
code.call(rax); code.call(rax);
break; break;
case 0x2E: case 0x2E:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsub); code.mov(rax, (u64)dsub);
code.call(rax); code.call(rax);
break; break;
case 0x2F: case 0x2F:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsubu); code.mov(rax, (u64)dsubu);
code.call(rax); code.call(rax);
break; break;
@@ -291,32 +291,32 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) {
res = true; res = true;
break; break;
case 0x38: case 0x38:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsll); code.mov(rax, (u64)dsll);
code.call(rax); code.call(rax);
break; break;
case 0x3A: case 0x3A:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsrl); code.mov(rax, (u64)dsrl);
code.call(rax); code.call(rax);
break; break;
case 0x3B: case 0x3B:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsra); code.mov(rax, (u64)dsra);
code.call(rax); code.call(rax);
break; break;
case 0x3C: case 0x3C:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsll32); code.mov(rax, (u64)dsll32);
code.call(rax); code.call(rax);
break; break;
case 0x3E: case 0x3E:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsrl32); code.mov(rax, (u64)dsrl32);
code.call(rax); code.call(rax);
break; break;
case 0x3F: case 0x3F:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)dsra32); code.mov(rax, (u64)dsra32);
code.call(rax); code.call(rax);
break; break;
@@ -327,12 +327,12 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) {
return res; return res;
} }
bool Dynarec::regimm(n64::Registers& regs, u32 instr) { bool Dynarec::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 0x00:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(r8, 0); code.cmp(r8, 0);
@@ -341,7 +341,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x01: case 0x01:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(r8, 0); code.cmp(r8, 0);
@@ -350,7 +350,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x02: case 0x02:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(r8, 0); code.cmp(r8, 0);
@@ -359,7 +359,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x03: case 0x03:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(r8, 0); code.cmp(r8, 0);
@@ -416,7 +416,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x10: case 0x10:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(rcx, 0); code.cmp(rcx, 0);
@@ -425,7 +425,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x11: case 0x11:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(rcx, 0); code.cmp(rcx, 0);
@@ -434,7 +434,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x12: case 0x12:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(rcx, 0); code.cmp(rcx, 0);
@@ -443,7 +443,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x13: case 0x13:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(rcx, 0); code.cmp(rcx, 0);
@@ -458,28 +458,28 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) {
return true; return true;
} }
bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { bool Dynarec::Exec(Mem& mem, u32 instr) {
u8 mask = (instr >> 26) & 0x3f; u8 mask = (instr >> 26) & 0x3f;
bool res = false; bool res = false;
// 00rr_rccc // 00rr_rccc
switch(mask) { // TODO: named constants for clearer code switch(mask) { // TODO: named constants for clearer code
case 0x00: res = special(regs, instr); break; case 0x00: res = special(instr); break;
case 0x01: res = regimm(regs, instr); break; case 0x01: res = regimm(instr); break;
case 0x02: case 0x02:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)j); code.mov(rax, (u64)j);
code.call(rax); code.call(rax);
res = true; res = true;
break; break;
case 0x03: case 0x03:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)jal); code.mov(rax, (u64)jal);
code.call(rax); code.call(rax);
res = true; res = true;
break; break;
case 0x04: case 0x04:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
@@ -490,7 +490,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
res = true; res = true;
break; break;
case 0x05: case 0x05:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
@@ -501,7 +501,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
res = true; res = true;
break; break;
case 0x06: case 0x06:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.test(r8, r8); code.test(r8, r8);
@@ -511,7 +511,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
res = true; res = true;
break; break;
case 0x07: case 0x07:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.test(r8, r8); code.test(r8, r8);
@@ -521,51 +521,50 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
res = true; res = true;
break; break;
case 0x08: case 0x08:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)addi); code.mov(rax, (u64)addi);
code.call(rax); code.call(rax);
break; break;
case 0x09: case 0x09:
emitBreakpoint(); code.mov(rsi, instr);
code.mov(rsi, (u64)instr);
code.mov(rax, (u64)addiu); code.mov(rax, (u64)addiu);
code.call(rax); code.call(rax);
break; break;
case 0x0A: case 0x0A:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)slti); code.mov(rax, (u64)slti);
code.call(rax); code.call(rax);
break; break;
case 0x0B: case 0x0B:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)sltiu); code.mov(rax, (u64)sltiu);
code.call(rax); code.call(rax);
break; break;
case 0x0C: case 0x0C:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)andi); code.mov(rax, (u64)andi);
code.call(rax); code.call(rax);
break; break;
case 0x0D: case 0x0D:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)ori); code.mov(rax, (u64)ori);
code.call(rax); code.call(rax);
break; break;
case 0x0E: case 0x0E:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)xori); code.mov(rax, (u64)xori);
code.call(rax); code.call(rax);
break; break;
case 0x0F: case 0x0F:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)lui); code.mov(rax, (u64)lui);
code.call(rax); code.call(rax);
break; break;
case 0x10: cop0Decode(regs, instr, *this); break; case 0x10: cop0Decode(regs, instr, *this); break;
case 0x11: res = cop1Decode(regs, instr, *this); break; case 0x11: res = cop1Decode(regs, instr, *this); break;
case 0x12: cop2Decode(regs, instr); break; case 0x12: cop2Decode(instr); break;
case 0x14: case 0x14:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
@@ -575,7 +574,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x15: case 0x15:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
@@ -585,7 +584,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x16: case 0x16:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(r8, 0); code.cmp(r8, 0);
@@ -594,7 +593,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x17: case 0x17:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]);
code.xor_(rdx, rdx); code.xor_(rdx, rdx);
code.cmp(r8, 0); code.cmp(r8, 0);
@@ -603,186 +602,186 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) {
code.call(rax); code.call(rax);
break; break;
case 0x18: case 0x18:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)daddi); code.mov(rax, (u64)daddi);
code.call(rax); code.call(rax);
break; break;
case 0x19: case 0x19:
code.mov(rsi, (u64)instr); code.mov(rsi, instr);
code.mov(rax, (u64)daddiu); code.mov(rax, (u64)daddiu);
code.call(rax); code.call(rax);
break; break;
case 0x1A: case 0x1A:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)ldl); code.mov(rax, (u64)ldl);
code.call(rax); code.call(rax);
break; break;
case 0x1B: case 0x1B:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)ldr); code.mov(rax, (u64)ldr);
code.call(rax); code.call(rax);
break; break;
case 0x1F: Util::panic("[RECOMPILER] Unhandled reserved instruction exception {:016X}\n", regs.oldPC); break; case 0x1F: Util::panic("[RECOMPILER] Unhandled reserved instruction exception {:016X}\n", regs.oldPC); break;
case 0x20: case 0x20:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lb); code.mov(rax, (u64)lb);
code.call(rax); code.call(rax);
break; break;
case 0x21: case 0x21:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lh); code.mov(rax, (u64)lh);
code.call(rax); code.call(rax);
break; break;
case 0x22: case 0x22:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lwl); code.mov(rax, (u64)lwl);
code.call(rax); code.call(rax);
break; break;
case 0x23: case 0x23:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lw); code.mov(rax, (u64)lw);
code.call(rax); code.call(rax);
break; break;
case 0x24: case 0x24:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lbu); code.mov(rax, (u64)lbu);
code.call(rax); code.call(rax);
break; break;
case 0x25: case 0x25:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lhu); code.mov(rax, (u64)lhu);
code.call(rax); code.call(rax);
break; break;
case 0x26: case 0x26:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lwr); code.mov(rax, (u64)lwr);
code.call(rax); code.call(rax);
break; break;
case 0x27: case 0x27:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lwu); code.mov(rax, (u64)lwu);
code.call(rax); code.call(rax);
break; break;
case 0x28: case 0x28:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sb); code.mov(rax, (u64)sb);
code.call(rax); code.call(rax);
break; break;
case 0x29: case 0x29:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sh); code.mov(rax, (u64)sh);
code.call(rax); code.call(rax);
break; break;
case 0x2A: case 0x2A:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)swl); code.mov(rax, (u64)swl);
code.call(rax); code.call(rax);
break; break;
case 0x2B: case 0x2B:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sw); code.mov(rax, (u64)sw);
code.call(rax); code.call(rax);
break; break;
case 0x2C: case 0x2C:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sdl); code.mov(rax, (u64)sdl);
code.call(rax); code.call(rax);
break; break;
case 0x2D: case 0x2D:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sdr); code.mov(rax, (u64)sdr);
code.call(rax); code.call(rax);
break; break;
case 0x2E: case 0x2E:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)swr); code.mov(rax, (u64)swr);
code.call(rax); code.call(rax);
break; break;
case 0x2F: break; // CACHE case 0x2F: break; // CACHE
case 0x30: case 0x30:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)ll); code.mov(rax, (u64)ll);
code.call(rax); code.call(rax);
break; break;
case 0x31: case 0x31:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lwc1); code.mov(rax, (u64)lwc1);
code.call(rax); code.call(rax);
break; break;
case 0x34: case 0x34:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)lld); code.mov(rax, (u64)lld);
code.call(rax); code.call(rax);
break; break;
case 0x35: case 0x35:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)ldc1); code.mov(rax, (u64)ldc1);
code.call(rax); code.call(rax);
break; break;
case 0x37: case 0x37:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)ld); code.mov(rax, (u64)ld);
code.call(rax); code.call(rax);
break; break;
case 0x38: case 0x38:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sc); code.mov(rax, (u64)sc);
code.call(rax); code.call(rax);
break; break;
case 0x39: case 0x39:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)swc1); code.mov(rax, (u64)swc1);
code.call(rax); code.call(rax);
break; break;
case 0x3C: case 0x3C:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)scd); code.mov(rax, (u64)scd);
code.call(rax); code.call(rax);
break; break;
case 0x3D: case 0x3D:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)instr); code.mov(rdx, instr);
code.mov(rax, (u64)sdc1); code.mov(rax, (u64)sdc1);
code.call(rax); code.call(rax);
break; break;
case 0x3F: case 0x3F:
code.mov(rsi, (u64)&mem); code.mov(rsi, (u64)&mem);
code.mov(rdx, (u64)this); code.mov(rdx, (u64)this);
code.mov(rcx, (u64)instr); code.mov(rcx, instr);
code.mov(rax, (u64)sd); code.mov(rax, (u64)sd);
code.call(rax); code.call(rax);
break; break;

View File

@@ -41,6 +41,7 @@ void addiu(Registers& regs, u32 instr) {
s16 imm = (s16)(instr); s16 imm = (s16)(instr);
s32 result = rs + imm; s32 result = rs + imm;
regs.gpr[RT(instr)] = result; regs.gpr[RT(instr)] = result;
Util::print("addiu {:08X}, {:04X} = {:08X} [reg: {:016X}]\n", (u32)rs, imm, (u32)result, (u64)regs.gpr[RT(instr)]);
} }
void dadd(Registers& regs, u32 instr) { void dadd(Registers& regs, u32 instr) {
@@ -146,6 +147,7 @@ void ddivu(Registers& regs, u32 instr) {
} }
void branch(Registers& regs, bool cond, s64 address) { void branch(Registers& regs, bool cond, s64 address) {
//Util::debug("\t\tJIT branch from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
regs.nextPC = address; regs.nextPC = address;
@@ -155,8 +157,10 @@ void branch(Registers& regs, bool cond, s64 address) {
void branch_likely(Registers& regs, bool cond, s64 address) { void branch_likely(Registers& regs, bool cond, s64 address) {
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
//Util::debug("\t\tJIT branch likely taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
regs.nextPC = address; regs.nextPC = address;
} else { } else {
//Util::debug("\t\tJIT branch likely not taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
regs.SetPC(regs.nextPC); regs.SetPC(regs.nextPC);
} }
} }

View File

@@ -20,65 +20,39 @@ inline int PushRoundingMode(const FCR31& fcr31) {
#define PUSHROUNDINGMODE int og = PushRoundingMode(fcr31) #define PUSHROUNDINGMODE int og = PushRoundingMode(fcr31)
#define POPROUNDINGMODE fesetround(og) #define POPROUNDINGMODE fesetround(og)
#ifdef _WIN32 #define checknanregs(fs, ft) do { \
#define isnanf isnan if(std::isnan(fs) || std::isnan(ft)) { \
#define checknanregsf(fs, ft) \
if(isnanf(fs) || isnanf(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \ regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \ regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \ return; \
} } \
} while(0)
#define checknanregsd(fs, ft) \
if(isnan(fs) || isnan(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \
}
#else
#define checknanregsf(fs, ft) \
if(isnanf(fs) || isnanf(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \
}
#define checknanregsd(fs, ft) \
if(isnan(fs) || isnan(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, true); \
return; \
}
#endif
void Cop1::absd(Registers& regs, u32 instr) { void Cop1::absd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
SetCop1Reg<double>(regs.cop0, FD(instr), fabs(fs)); SetCop1Reg<double>(regs.cop0, FD(instr), std::abs(fs));
} }
void Cop1::abss(Registers& regs, u32 instr) { void Cop1::abss(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
SetCop1Reg<float>(regs.cop0, FD(instr), fabsf(fs)); SetCop1Reg<float>(regs.cop0, FD(instr), std::abs(fs));
} }
void Cop1::absw(Registers& regs, u32 instr) { void Cop1::absw(Registers& regs, u32 instr) {
s32 fs = GetReg<s32>(regs.cop0, FS(instr)); s32 fs = GetReg<s32>(regs.cop0, FS(instr));
SetReg<u32>(regs.cop0, FD(instr), abs(fs)); SetReg<u32>(regs.cop0, FD(instr), std::abs(fs));
} }
void Cop1::absl(Registers& regs, u32 instr) { void Cop1::absl(Registers& regs, u32 instr) {
s64 fs = GetReg<s64>(regs.cop0, FS(instr)); s64 fs = GetReg<s64>(regs.cop0, FS(instr));
SetReg(regs.cop0, FD(instr), labs(fs)); SetReg(regs.cop0, FD(instr), std::abs(fs));
} }
void Cop1::adds(Registers& regs, u32 instr) { void Cop1::adds(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
float ft = GetCop1Reg<float>(regs.cop0, FT(instr)); float ft = GetCop1Reg<float>(regs.cop0, FT(instr));
checknanregsf(fs, ft) checknanregs(fs, ft);
float result = fs + ft; float result = fs + ft;
SetCop1Reg<float>(regs.cop0, FD(instr), result); SetCop1Reg<float>(regs.cop0, FD(instr), result);
} }
@@ -86,32 +60,32 @@ void Cop1::adds(Registers& regs, u32 instr) {
void Cop1::addd(Registers& regs, u32 instr) { void Cop1::addd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
double ft = GetCop1Reg<double>(regs.cop0, FT(instr)); double ft = GetCop1Reg<double>(regs.cop0, FT(instr));
checknanregsf(fs, ft) checknanregs(fs, ft);
double result = fs + ft; double result = fs + ft;
SetCop1Reg<double>(regs.cop0, FD(instr), result); SetCop1Reg<double>(regs.cop0, FD(instr), result);
} }
void Cop1::ceills(Registers& regs, u32 instr) { void Cop1::ceills(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
s64 result = ceilf(fs); s64 result = std::ceil(fs);
SetReg<u64>(regs.cop0, FD(instr), result); SetReg<u64>(regs.cop0, FD(instr), result);
} }
void Cop1::ceilws(Registers& regs, u32 instr) { void Cop1::ceilws(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
s32 result = ceilf(fs); s32 result = std::ceil(fs);
SetReg<u32>(regs.cop0, FD(instr), result); SetReg<u32>(regs.cop0, FD(instr), result);
} }
void Cop1::ceilld(Registers& regs, u32 instr) { void Cop1::ceilld(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
s64 result = ceil(fs); s64 result = std::ceil(fs);
SetReg<u64>(regs.cop0, FD(instr), result); SetReg<u64>(regs.cop0, FD(instr), result);
} }
void Cop1::ceilwd(Registers& regs, u32 instr) { void Cop1::ceilwd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
s32 result = ceil(fs); s32 result = std::ceil(fs);
SetReg<u32>(regs.cop0, FD(instr), result); SetReg<u32>(regs.cop0, FD(instr), result);
} }
@@ -411,60 +385,60 @@ void Cop1::negd(Registers &regs, u32 instr) {
void Cop1::sqrts(Registers &regs, u32 instr) { void Cop1::sqrts(Registers &regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
SetCop1Reg<float>(regs.cop0, FD(instr), sqrtf(fs)); SetCop1Reg<float>(regs.cop0, FD(instr), std::sqrt(fs));
} }
void Cop1::sqrtd(Registers &regs, u32 instr) { void Cop1::sqrtd(Registers &regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
SetCop1Reg<double>(regs.cop0, FD(instr), sqrt(fs)); SetCop1Reg<double>(regs.cop0, FD(instr), std::sqrt(fs));
} }
void Cop1::roundls(Registers& regs, u32 instr) { void Cop1::roundls(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
SetReg<u64>(regs.cop0, FD(instr), (s32)nearbyintf(fs)); SetReg<u64>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void Cop1::roundld(Registers& regs, u32 instr) { void Cop1::roundld(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
SetReg<u64>(regs.cop0, FD(instr), (s64)nearbyint(fs)); SetReg<u64>(regs.cop0, FD(instr), (s64)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void Cop1::roundws(Registers& regs, u32 instr) { void Cop1::roundws(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
SetReg<u32>(regs.cop0, FD(instr), (s32)nearbyintf(fs)); SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void Cop1::roundwd(Registers& regs, u32 instr) { void Cop1::roundwd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
SetReg<u32>(regs.cop0, FD(instr), (s32)nearbyint(fs)); SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void Cop1::floorls(Registers& regs, u32 instr) { void Cop1::floorls(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
SetReg<u64>(regs.cop0, FD(instr), (s64)floorf(fs)); SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void Cop1::floorld(Registers& regs, u32 instr) { void Cop1::floorld(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
SetReg<u64>(regs.cop0, FD(instr), (s64)floor(fs)); SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void Cop1::floorws(Registers& regs, u32 instr) { void Cop1::floorws(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
SetReg<u32>(regs.cop0, FD(instr), (s64)floorf(fs)); SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void Cop1::floorwd(Registers& regs, u32 instr) { void Cop1::floorwd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
SetReg<u32>(regs.cop0, FD(instr), (s64)floor(fs)); SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) { void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) {
@@ -551,25 +525,25 @@ void Cop1::sdc1(Registers& regs, Mem& mem, u32 instr) {
void Cop1::truncws(Registers& regs, u32 instr) { void Cop1::truncws(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
s32 result = (s32)truncf(fs); s32 result = (s32)std::trunc(fs);
SetReg<u32>(regs.cop0, FD(instr), result); SetReg<u32>(regs.cop0, FD(instr), result);
} }
void Cop1::truncwd(Registers& regs, u32 instr) { void Cop1::truncwd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
s32 result = (s32)trunc(fs); s32 result = (s32)std::trunc(fs);
SetReg<u32>(regs.cop0, FD(instr), result); SetReg<u32>(regs.cop0, FD(instr), result);
} }
void Cop1::truncls(Registers& regs, u32 instr) { void Cop1::truncls(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
s64 result = (s64)truncf(fs); s64 result = (s64)std::trunc(fs);
SetReg<u64>(regs.cop0, FD(instr), result); SetReg<u64>(regs.cop0, FD(instr), result);
} }
void Cop1::truncld(Registers& regs, u32 instr) { void Cop1::truncld(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
s64 result = (s64)trunc(fs); s64 result = (s64)std::trunc(fs);
SetReg<u64>(regs.cop0, FD(instr), result); SetReg<u64>(regs.cop0, FD(instr), result);
} }

View File

@@ -2,172 +2,172 @@
#include <log.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
void Interpreter::special(Registers& regs, u32 instr) { void Interpreter::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 0:
if (instr != 0) { if (instr != 0) {
sll(regs, instr); sll(instr);
} }
break; break;
case 0x02: srl(regs, instr); break; case 0x02: srl(instr); break;
case 0x03: sra(regs, instr); break; case 0x03: sra(instr); break;
case 0x04: sllv(regs, instr); break; case 0x04: sllv(instr); break;
case 0x06: srlv(regs, instr); break; case 0x06: srlv(instr); break;
case 0x07: srav(regs, instr); break; case 0x07: srav(instr); break;
case 0x08: jr(regs, instr); break; case 0x08: jr(instr); break;
case 0x09: jalr(regs, instr); break; case 0x09: jalr(instr); break;
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, true); break; case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, true); break;
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, true); break; case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, true); break;
case 0x0F: break; // SYNC case 0x0F: break; // SYNC
case 0x10: mfhi(regs, instr); break; case 0x10: mfhi(instr); break;
case 0x11: mthi(regs, instr); break; case 0x11: mthi(instr); break;
case 0x12: mflo(regs, instr); break; case 0x12: mflo(instr); break;
case 0x13: mtlo(regs, instr); break; case 0x13: mtlo(instr); break;
case 0x14: dsllv(regs, instr); break; case 0x14: dsllv(instr); break;
case 0x16: dsrlv(regs, instr); break; case 0x16: dsrlv(instr); break;
case 0x17: dsrav(regs, instr); break; case 0x17: dsrav(instr); break;
case 0x18: mult(regs, instr); break; case 0x18: mult(instr); break;
case 0x19: multu(regs, instr); break; case 0x19: multu(instr); break;
case 0x1A: div(regs, instr); break; case 0x1A: div(instr); break;
case 0x1B: divu(regs, instr); break; case 0x1B: divu(instr); break;
case 0x1C: dmult(regs, instr); break; case 0x1C: dmult(instr); break;
case 0x1D: dmultu(regs, instr); break; case 0x1D: dmultu(instr); break;
case 0x1E: ddiv(regs, instr); break; case 0x1E: ddiv(instr); break;
case 0x1F: ddivu(regs, instr); break; case 0x1F: ddivu(instr); break;
case 0x20: add(regs, instr); break; case 0x20: add(instr); break;
case 0x21: addu(regs, instr); break; case 0x21: addu(instr); break;
case 0x22: sub(regs, instr); break; case 0x22: sub(instr); break;
case 0x23: subu(regs, instr); break; case 0x23: subu(instr); break;
case 0x24: and_(regs, instr); break; case 0x24: and_(instr); break;
case 0x25: or_(regs, instr); break; case 0x25: or_(instr); break;
case 0x26: xor_(regs, instr); break; case 0x26: xor_(instr); break;
case 0x27: nor(regs, instr); break; case 0x27: nor(instr); break;
case 0x2A: slt(regs, instr); break; case 0x2A: slt(instr); break;
case 0x2B: sltu(regs, instr); break; case 0x2B: sltu(instr); break;
case 0x2C: dadd(regs, instr); break; case 0x2C: dadd(instr); break;
case 0x2D: daddu(regs, instr); break; case 0x2D: daddu(instr); break;
case 0x2E: dsub(regs, instr); break; case 0x2E: dsub(instr); break;
case 0x2F: dsubu(regs, instr); break; case 0x2F: dsubu(instr); break;
case 0x30: trap(regs, regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; case 0x30: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break;
case 0x31: trap(regs, (u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; case 0x31: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break;
case 0x32: trap(regs, regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; case 0x32: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break;
case 0x33: trap(regs, (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; case 0x33: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break;
case 0x34: trap(regs, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
case 0x36: trap(regs, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; case 0x36: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
case 0x38: dsll(regs, instr); break; case 0x38: dsll(instr); break;
case 0x3A: dsrl(regs, instr); break; case 0x3A: dsrl(instr); break;
case 0x3B: dsra(regs, instr); break; case 0x3B: dsra(instr); break;
case 0x3C: dsll32(regs, instr); break; case 0x3C: dsll32(instr); break;
case 0x3E: dsrl32(regs, instr); break; case 0x3E: dsrl32(instr); break;
case 0x3F: dsra32(regs, instr); break; case 0x3F: dsra32(instr); break;
default: default:
Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
} }
} }
void Interpreter::regimm(Registers& regs, u32 instr) { void Interpreter::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: b(regs, instr, regs.gpr[RS(instr)] < 0); break; case 0x00: b(instr, regs.gpr[RS(instr)] < 0); break;
case 0x01: b(regs, instr, regs.gpr[RS(instr)] >= 0); break; case 0x01: b(instr, regs.gpr[RS(instr)] >= 0); break;
case 0x02: bl(regs, instr, regs.gpr[RS(instr)] < 0); break; case 0x02: bl(instr, regs.gpr[RS(instr)] < 0); break;
case 0x03: bl(regs, instr, regs.gpr[RS(instr)] >= 0); break; case 0x03: bl(instr, regs.gpr[RS(instr)] >= 0); break;
case 0x08: trap(regs, regs.gpr[RS(instr)] >= s64(s16(instr))); break; case 0x08: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break;
case 0x09: trap(regs, u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; case 0x09: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break;
case 0x0A: trap(regs, regs.gpr[RS(instr)] < s64(s16(instr))); break; case 0x0A: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break;
case 0x0B: trap(regs, u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; case 0x0B: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break;
case 0x0C: trap(regs, regs.gpr[RS(instr)] == s64(s16(instr))); break; case 0x0C: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break;
case 0x0E: trap(regs, regs.gpr[RS(instr)] != s64(s16(instr))); break; case 0x0E: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break;
case 0x10: blink(regs, instr, regs.gpr[RS(instr)] < 0); break; case 0x10: blink(instr, regs.gpr[RS(instr)] < 0); break;
case 0x11: blink(regs, instr, regs.gpr[RS(instr)] >= 0); break; case 0x11: blink(instr, regs.gpr[RS(instr)] >= 0); break;
case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break; case 0x12: bllink(instr, regs.gpr[RS(instr)] < 0); break;
case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break; case 0x13: bllink(instr, regs.gpr[RS(instr)] >= 0); break;
default: default:
Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
} }
} }
void Interpreter::cop2Decode(Registers& regs, u32 instr) { void Interpreter::cop2Decode(u32 instr) {
if(!regs.cop0.status.cu2) { if(!regs.cop0.status.cu2) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 2, true);
return; return;
} }
switch(RS(instr)) { switch(RS(instr)) {
case 0x00: mfc2(regs, instr); break; case 0x00: mfc2(instr); break;
case 0x01: dmfc2(regs, instr); break; case 0x01: dmfc2(instr); break;
case 0x02: cfc2(regs, instr); break; case 0x02: cfc2(instr); break;
case 0x04: mtc2(regs, instr); break; case 0x04: mtc2(instr); break;
case 0x05: dmtc2(regs, instr); break; case 0x05: dmtc2(instr); break;
case 0x06: ctc2(regs, instr); break; case 0x06: ctc2(instr); break;
default: default:
FireException(regs, ExceptionCode::ReservedInstruction, 2, true); FireException(regs, ExceptionCode::ReservedInstruction, 2, true);
} }
} }
void Interpreter::Exec(Registers& regs, Mem& mem, u32 instr) { void Interpreter::Exec(Mem& mem, 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(regs, instr); break; case 0x00: special(instr); break;
case 0x01: regimm(regs, instr); break; case 0x01: regimm(instr); break;
case 0x02: j(regs, instr); break; case 0x02: j(instr); break;
case 0x03: jal(regs, instr); break; case 0x03: jal(instr); break;
case 0x04: b(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; case 0x04: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
case 0x05: { case 0x05: {
//fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]); //fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]);
b(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]);
} break; } break;
case 0x06: b(regs, instr, regs.gpr[RS(instr)] <= 0); break; case 0x06: b(instr, regs.gpr[RS(instr)] <= 0); break;
case 0x07: b(regs, instr, regs.gpr[RS(instr)] > 0); break; case 0x07: b(instr, regs.gpr[RS(instr)] > 0); break;
case 0x08: addi(regs, instr); break; case 0x08: addi(instr); break;
case 0x09: addiu(regs, instr); break; case 0x09: addiu(instr); break;
case 0x0A: slti(regs, instr); break; case 0x0A: slti(instr); break;
case 0x0B: sltiu(regs, instr); break; case 0x0B: sltiu(instr); break;
case 0x0C: andi(regs, instr); break; case 0x0C: andi(instr); break;
case 0x0D: ori(regs, instr); break; case 0x0D: ori(instr); break;
case 0x0E: xori(regs, instr); break; case 0x0E: xori(instr); break;
case 0x0F: lui(regs, instr); break; case 0x0F: lui(instr); break;
case 0x10: regs.cop0.decode(regs, mem, instr); break; case 0x10: regs.cop0.decode(regs, mem, instr); break;
case 0x11: regs.cop1.decode(regs, *this, instr); break; case 0x11: regs.cop1.decode(regs, *this, instr); break;
case 0x12: cop2Decode(regs, instr); break; case 0x12: cop2Decode(instr); break;
case 0x14: bl(regs, 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(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
case 0x16: bl(regs, instr, regs.gpr[RS(instr)] <= 0); break; case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;
case 0x17: bl(regs, instr, regs.gpr[RS(instr)] > 0); break; case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break;
case 0x18: daddi(regs, instr); break; case 0x18: daddi(instr); break;
case 0x19: daddiu(regs, instr); break; case 0x19: daddiu(instr); break;
case 0x1A: ldl(regs, mem, instr); break; case 0x1A: ldl(mem, instr); break;
case 0x1B: ldr(regs, mem, instr); break; case 0x1B: ldr(mem, instr); break;
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break;
case 0x20: lb(regs, mem, instr); break; case 0x20: lb(mem, instr); break;
case 0x21: lh(regs, mem, instr); break; case 0x21: lh(mem, instr); break;
case 0x22: lwl(regs, mem, instr); break; case 0x22: lwl(mem, instr); break;
case 0x23: lw(regs, mem, instr); break; case 0x23: lw(mem, instr); break;
case 0x24: lbu(regs, mem, instr); break; case 0x24: lbu(mem, instr); break;
case 0x25: lhu(regs, mem, instr); break; case 0x25: lhu(mem, instr); break;
case 0x26: lwr(regs, mem, instr); break; case 0x26: lwr(mem, instr); break;
case 0x27: lwu(regs, mem, instr); break; case 0x27: lwu(mem, instr); break;
case 0x28: sb(regs, mem, instr); break; case 0x28: sb(mem, instr); break;
case 0x29: sh(regs, mem, instr); break; case 0x29: sh(mem, instr); break;
case 0x2A: swl(regs, mem, instr); break; case 0x2A: swl(mem, instr); break;
case 0x2B: sw(regs, mem, instr); break; case 0x2B: sw(mem, instr); break;
case 0x2C: sdl(regs, mem, instr); break; case 0x2C: sdl(mem, instr); break;
case 0x2D: sdr(regs, mem, instr); break; case 0x2D: sdr(mem, instr); break;
case 0x2E: swr(regs, mem, instr); break; case 0x2E: swr(mem, instr); break;
case 0x2F: break; // CACHE case 0x2F: break; // CACHE
case 0x30: ll(regs, mem, instr); break; case 0x30: ll(mem, instr); break;
case 0x31: regs.cop1.lwc1(regs, mem, instr); break; case 0x31: regs.cop1.lwc1(regs, mem, instr); break;
case 0x34: lld(regs, mem, instr); break; case 0x34: lld(mem, instr); break;
case 0x35: regs.cop1.ldc1(regs, mem, instr); break; case 0x35: regs.cop1.ldc1(regs, mem, instr); break;
case 0x37: ld(regs, mem, instr); break; case 0x37: ld(mem, instr); break;
case 0x38: sc(regs, mem, instr); break; case 0x38: sc(mem, instr); break;
case 0x39: regs.cop1.swc1(regs, mem, instr); break; case 0x39: regs.cop1.swc1(regs, mem, instr); break;
case 0x3C: scd(regs, mem, instr); break; case 0x3C: scd(mem, instr); break;
case 0x3D: regs.cop1.sdc1(regs, mem, instr); break; case 0x3D: regs.cop1.sdc1(regs, mem, instr); break;
case 0x3F: sd(regs, mem, instr); break; case 0x3F: sd(mem, instr); break;
default: default:
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC); Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC);
} }

View File

@@ -6,7 +6,7 @@
#define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) #define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
namespace n64 { namespace n64 {
void Interpreter::add(Registers& regs, u32 instr) { void Interpreter::add(u32 instr) {
u32 rs = (s32)regs.gpr[RS(instr)]; u32 rs = (s32)regs.gpr[RS(instr)];
u32 rt = (s32)regs.gpr[RT(instr)]; u32 rt = (s32)regs.gpr[RT(instr)];
u32 result = rs + rt; u32 result = rs + rt;
@@ -17,14 +17,14 @@ void Interpreter::add(Registers& regs, u32 instr) {
} }
} }
void Interpreter::addu(Registers& regs, u32 instr) { void Interpreter::addu(u32 instr) {
s32 rs = (s32)regs.gpr[RS(instr)]; s32 rs = (s32)regs.gpr[RS(instr)];
s32 rt = (s32)regs.gpr[RT(instr)]; s32 rt = (s32)regs.gpr[RT(instr)];
s32 result = rs + rt; s32 result = rs + rt;
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::addi(Registers& regs, u32 instr) { void Interpreter::addi(u32 instr) {
u32 rs = regs.gpr[RS(instr)]; u32 rs = regs.gpr[RS(instr)];
u32 imm = s32(s16(instr)); u32 imm = s32(s16(instr));
u32 result = rs + imm; u32 result = rs + imm;
@@ -35,14 +35,14 @@ void Interpreter::addi(Registers& regs, u32 instr) {
} }
} }
void Interpreter::addiu(Registers& regs, u32 instr) { void Interpreter::addiu(u32 instr) {
s32 rs = (s32)regs.gpr[RS(instr)]; s32 rs = (s32)regs.gpr[RS(instr)];
s16 imm = (s16)(instr); s16 imm = (s16)(instr);
s32 result = rs + imm; s32 result = rs + imm;
regs.gpr[RT(instr)] = result; regs.gpr[RT(instr)] = result;
} }
void Interpreter::dadd(Registers& regs, u32 instr) { void Interpreter::dadd(u32 instr) {
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 result = rt + rs; u64 result = rt + rs;
@@ -53,13 +53,13 @@ void Interpreter::dadd(Registers& regs, u32 instr) {
} }
} }
void Interpreter::daddu(Registers& regs, u32 instr) { void Interpreter::daddu(u32 instr) {
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
regs.gpr[RD(instr)] = rs + rt; regs.gpr[RD(instr)] = rs + rt;
} }
void Interpreter::daddi(Registers& regs, u32 instr) { void Interpreter::daddi(u32 instr) {
u64 imm = s64(s16(instr)); u64 imm = s64(s16(instr));
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u64 result = imm + rs; u64 result = imm + rs;
@@ -70,13 +70,13 @@ void Interpreter::daddi(Registers& regs, u32 instr) {
} }
} }
void Interpreter::daddiu(Registers& regs, u32 instr) { void Interpreter::daddiu(u32 instr) {
s16 imm = (s16)(instr); s16 imm = (s16)(instr);
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
regs.gpr[RT(instr)] = rs + imm; regs.gpr[RT(instr)] = rs + imm;
} }
void Interpreter::div(Registers& regs, u32 instr) { void Interpreter::div(u32 instr) {
s64 dividend = (s32)regs.gpr[RS(instr)]; s64 dividend = (s32)regs.gpr[RS(instr)];
s64 divisor = (s32)regs.gpr[RT(instr)]; s64 divisor = (s32)regs.gpr[RT(instr)];
@@ -95,7 +95,7 @@ void Interpreter::div(Registers& regs, u32 instr) {
} }
} }
void Interpreter::divu(Registers& regs, u32 instr) { void Interpreter::divu(u32 instr) {
u32 dividend = regs.gpr[RS(instr)]; u32 dividend = regs.gpr[RS(instr)];
u32 divisor = regs.gpr[RT(instr)]; u32 divisor = regs.gpr[RT(instr)];
if(divisor == 0) { if(divisor == 0) {
@@ -109,7 +109,7 @@ void Interpreter::divu(Registers& regs, u32 instr) {
} }
} }
void Interpreter::ddiv(Registers& regs, u32 instr) { void Interpreter::ddiv(u32 instr) {
s64 dividend = regs.gpr[RS(instr)]; s64 dividend = regs.gpr[RS(instr)];
s64 divisor = regs.gpr[RT(instr)]; s64 divisor = regs.gpr[RT(instr)];
if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) {
@@ -130,7 +130,7 @@ void Interpreter::ddiv(Registers& regs, u32 instr) {
} }
} }
void Interpreter::ddivu(Registers& regs, u32 instr) { void Interpreter::ddivu(u32 instr) {
u64 dividend = regs.gpr[RS(instr)]; u64 dividend = regs.gpr[RS(instr)];
u64 divisor = regs.gpr[RT(instr)]; u64 divisor = regs.gpr[RT(instr)];
if(divisor == 0) { if(divisor == 0) {
@@ -144,14 +144,14 @@ void Interpreter::ddivu(Registers& regs, u32 instr) {
} }
} }
void Interpreter::branch(Registers& regs, bool cond, s64 address) { void Interpreter::branch(bool cond, s64 address) {
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
regs.nextPC = address; regs.nextPC = address;
} }
} }
void Interpreter::branch_likely(Registers& regs, bool cond, s64 address) { void Interpreter::branch_likely(bool cond, s64 address) {
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
regs.nextPC = address; regs.nextPC = address;
@@ -160,44 +160,44 @@ void Interpreter::branch_likely(Registers& regs, bool cond, s64 address) {
} }
} }
void Interpreter::b(Registers& regs, u32 instr, bool cond) { void Interpreter::b(u32 instr, bool cond) {
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch(regs, cond, address); branch(cond, address);
} }
void Interpreter::blink(Registers& regs, u32 instr, bool cond) { void Interpreter::blink(u32 instr, bool cond) {
regs.gpr[31] = regs.nextPC; regs.gpr[31] = regs.nextPC;
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch(regs, cond, address); branch(cond, address);
} }
void Interpreter::bl(Registers& regs, u32 instr, bool cond) { void Interpreter::bl(u32 instr, bool cond) {
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch_likely(regs, cond, address); branch_likely(cond, address);
} }
void Interpreter::bllink(Registers& regs, u32 instr, bool cond) { void Interpreter::bllink(u32 instr, bool cond) {
regs.gpr[31] = regs.nextPC; regs.gpr[31] = regs.nextPC;
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch_likely(regs, cond, address); branch_likely(cond, address);
} }
void Interpreter::lui(Registers& regs, u32 instr) { void Interpreter::lui(u32 instr) {
s64 val = (s16)instr; s64 val = (s16)instr;
val <<= 16; val <<= 16;
regs.gpr[RT(instr)] = val; regs.gpr[RT(instr)] = val;
} }
void Interpreter::lb(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lb(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC); regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC);
} }
void Interpreter::lh(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lh(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) { if (check_address_error(address, 0b1)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -208,7 +208,7 @@ void Interpreter::lh(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC); regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC);
} }
void Interpreter::lw(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lw(Mem& mem, u32 instr) {
s16 offset = instr; s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
@@ -226,7 +226,7 @@ void Interpreter::lw(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::ll(Registers& regs, Mem& mem, u32 instr) { void Interpreter::ll(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 physical; u32 physical;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
@@ -240,7 +240,7 @@ void Interpreter::ll(Registers& regs, Mem& mem, u32 instr) {
regs.cop0.LLAddr = physical >> 4; regs.cop0.LLAddr = physical >> 4;
} }
void Interpreter::lwl(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lwl(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -255,7 +255,7 @@ void Interpreter::lwl(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::lwr(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lwr(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -270,7 +270,7 @@ void Interpreter::lwr(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::ld(Registers& regs, Mem& mem, u32 instr) { void Interpreter::ld(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b111)) { if (check_address_error(address, 0b111)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -282,7 +282,7 @@ void Interpreter::ld(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void Interpreter::lld(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lld(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -296,7 +296,7 @@ void Interpreter::lld(Registers& regs, Mem& mem, u32 instr) {
regs.cop0.LLAddr = paddr >> 4; regs.cop0.LLAddr = paddr >> 4;
} }
void Interpreter::ldl(Registers& regs, Mem& mem, u32 instr) { void Interpreter::ldl(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -311,7 +311,7 @@ void Interpreter::ldl(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::ldr(Registers& regs, Mem& mem, u32 instr) { void Interpreter::ldr(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -326,13 +326,13 @@ void Interpreter::ldr(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::lbu(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lbu(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u8 value = mem.Read8(regs, address, regs.oldPC); u8 value = mem.Read8(regs, address, regs.oldPC);
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void Interpreter::lhu(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lhu(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) { if (check_address_error(address, 0b1)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -344,7 +344,7 @@ void Interpreter::lhu(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void Interpreter::lwu(Registers& regs, Mem& mem, u32 instr) { void Interpreter::lwu(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -356,12 +356,12 @@ void Interpreter::lwu(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void Interpreter::sb(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sb(Mem& mem, u32 instr) {
u32 address = regs.gpr[RS(instr)] + (s16)instr; u32 address = regs.gpr[RS(instr)] + (s16)instr;
mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC); mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC);
} }
void Interpreter::sc(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sc(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -376,7 +376,7 @@ void Interpreter::sc(Registers& regs, Mem& mem, u32 instr) {
regs.cop0.llbit = false; regs.cop0.llbit = false;
} }
void Interpreter::scd(Registers& regs, Mem& mem, u32 instr) { void Interpreter::scd(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b111)) { if (check_address_error(address, 0b111)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -392,7 +392,7 @@ void Interpreter::scd(Registers& regs, Mem& mem, u32 instr) {
regs.cop0.llbit = false; regs.cop0.llbit = false;
} }
void Interpreter::sh(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sh(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) { if (check_address_error(address, 0b1)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -409,7 +409,7 @@ void Interpreter::sh(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::sw(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sw(Mem& mem, u32 instr) {
s16 offset = instr; s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
@@ -427,7 +427,7 @@ void Interpreter::sw(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::sd(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sd(Mem& mem, u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -445,7 +445,7 @@ void Interpreter::sd(Registers& regs, Mem& mem, u32 instr) {
} }
void Interpreter::sdl(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sdl(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -460,7 +460,7 @@ void Interpreter::sdl(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::sdr(Registers& regs, Mem& mem, u32 instr) { void Interpreter::sdr(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -475,7 +475,7 @@ void Interpreter::sdr(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::swl(Registers& regs, Mem& mem, u32 instr) { void Interpreter::swl(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -490,7 +490,7 @@ void Interpreter::swl(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::swr(Registers& regs, Mem& mem, u32 instr) { void Interpreter::swr(Mem& mem, u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -505,21 +505,21 @@ void Interpreter::swr(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void Interpreter::ori(Registers& regs, u32 instr) { void Interpreter::ori(u32 instr) {
s64 imm = (u16)instr; s64 imm = (u16)instr;
s64 result = imm | regs.gpr[RS(instr)]; s64 result = imm | regs.gpr[RS(instr)];
regs.gpr[RT(instr)] = result; regs.gpr[RT(instr)] = result;
} }
void Interpreter::or_(Registers& regs, u32 instr) { void Interpreter::or_(u32 instr) {
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)];
} }
void Interpreter::nor(Registers& regs, u32 instr) { void Interpreter::nor(u32 instr) {
regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]); regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]);
} }
void Interpreter::j(Registers& regs, u32 instr) { void Interpreter::j(u32 instr) {
s32 target = (instr & 0x3ffffff) << 2; s32 target = (instr & 0x3ffffff) << 2;
s64 address = (regs.oldPC & ~0xfffffff) | target; s64 address = (regs.oldPC & ~0xfffffff) | target;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
@@ -527,127 +527,127 @@ void Interpreter::j(Registers& regs, u32 instr) {
FireException(regs, ExceptionCode::DataBusError, 0, true); FireException(regs, ExceptionCode::DataBusError, 0, true);
} }
branch(regs, true, address); branch(true, address);
} }
void Interpreter::jal(Registers& regs, u32 instr) { void Interpreter::jal(u32 instr) {
regs.gpr[31] = regs.nextPC; regs.gpr[31] = regs.nextPC;
j(regs, instr); j(instr);
} }
void Interpreter::jalr(Registers& regs, u32 instr) { void Interpreter::jalr(u32 instr) {
branch(regs, true, regs.gpr[RS(instr)]); branch(true, regs.gpr[RS(instr)]);
regs.gpr[RD(instr)] = regs.pc + 4; regs.gpr[RD(instr)] = regs.pc + 4;
} }
void Interpreter::slti(Registers& regs, u32 instr) { void Interpreter::slti(u32 instr) {
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr); regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr);
} }
void Interpreter::sltiu(Registers& regs, u32 instr) { void Interpreter::sltiu(u32 instr) {
regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr); regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr);
} }
void Interpreter::slt(Registers& regs, u32 instr) { void Interpreter::slt(u32 instr) {
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)];
} }
void Interpreter::sltu(Registers& regs, u32 instr) { void Interpreter::sltu(u32 instr) {
regs.gpr[RD(instr)] = (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)];
} }
void Interpreter::xori(Registers& regs, u32 instr) { void Interpreter::xori(u32 instr) {
s64 imm = (u16)instr; s64 imm = (u16)instr;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm;
} }
void Interpreter::xor_(Registers& regs, u32 instr) { void Interpreter::xor_(u32 instr) {
regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)]; regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)];
} }
void Interpreter::andi(Registers& regs, u32 instr) { void Interpreter::andi(u32 instr) {
s64 imm = (u16)instr; s64 imm = (u16)instr;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm;
} }
void Interpreter::and_(Registers& regs, u32 instr) { void Interpreter::and_(u32 instr) {
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)];
} }
void Interpreter::sll(Registers& regs, u32 instr) { void Interpreter::sll(u32 instr) {
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s32 result = regs.gpr[RT(instr)] << sa; s32 result = regs.gpr[RT(instr)] << sa;
regs.gpr[RD(instr)] = (s64)result; regs.gpr[RD(instr)] = (s64)result;
} }
void Interpreter::sllv(Registers& regs, u32 instr) { void Interpreter::sllv(u32 instr) {
u8 sa = (regs.gpr[RS(instr)]) & 0x1F; u8 sa = (regs.gpr[RS(instr)]) & 0x1F;
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
s32 result = rt << sa; s32 result = rt << sa;
regs.gpr[RD(instr)] = (s64)result; regs.gpr[RD(instr)] = (s64)result;
} }
void Interpreter::dsll32(Registers& regs, u32 instr) { void Interpreter::dsll32(u32 instr) {
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s64 result = regs.gpr[RT(instr)] << (sa + 32); s64 result = regs.gpr[RT(instr)] << (sa + 32);
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::dsll(Registers& regs, u32 instr) { void Interpreter::dsll(u32 instr) {
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s64 result = regs.gpr[RT(instr)] << sa; s64 result = regs.gpr[RT(instr)] << sa;
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::dsllv(Registers& regs, u32 instr) { void Interpreter::dsllv(u32 instr) {
s64 sa = regs.gpr[RS(instr)] & 63; s64 sa = regs.gpr[RS(instr)] & 63;
s64 result = regs.gpr[RT(instr)] << sa; s64 result = regs.gpr[RT(instr)] << sa;
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::srl(Registers& regs, u32 instr) { void Interpreter::srl(u32 instr) {
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
u32 result = rt >> sa; u32 result = rt >> sa;
regs.gpr[RD(instr)] = (s32)result; regs.gpr[RD(instr)] = (s32)result;
} }
void Interpreter::srlv(Registers& regs, u32 instr) { void Interpreter::srlv(u32 instr) {
u8 sa = (regs.gpr[RS(instr)] & 0x1F); u8 sa = (regs.gpr[RS(instr)] & 0x1F);
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
s32 result = rt >> sa; s32 result = rt >> sa;
regs.gpr[RD(instr)] = (s64)result; regs.gpr[RD(instr)] = (s64)result;
} }
void Interpreter::dsrl(Registers& regs, u32 instr) { void Interpreter::dsrl(u32 instr) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
u64 result = rt >> sa; u64 result = rt >> sa;
regs.gpr[RD(instr)] = s64(result); regs.gpr[RD(instr)] = s64(result);
} }
void Interpreter::dsrlv(Registers& regs, u32 instr) { void Interpreter::dsrlv(u32 instr) {
u8 amount = (regs.gpr[RS(instr)] & 63); u8 amount = (regs.gpr[RS(instr)] & 63);
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 result = rt >> amount; u64 result = rt >> amount;
regs.gpr[RD(instr)] = s64(result); regs.gpr[RD(instr)] = s64(result);
} }
void Interpreter::dsrl32(Registers& regs, u32 instr) { void Interpreter::dsrl32(u32 instr) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
u64 result = rt >> (sa + 32); u64 result = rt >> (sa + 32);
regs.gpr[RD(instr)] = s64(result); regs.gpr[RD(instr)] = s64(result);
} }
void Interpreter::sra(Registers& regs, u32 instr) { void Interpreter::sra(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s32 result = rt >> sa; s32 result = rt >> sa;
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::srav(Registers& regs, u32 instr) { void Interpreter::srav(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
u8 sa = rs & 0x1f; u8 sa = rs & 0x1f;
@@ -655,14 +655,14 @@ void Interpreter::srav(Registers& regs, u32 instr) {
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::dsra(Registers& regs, u32 instr) { void Interpreter::dsra(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s64 result = rt >> sa; s64 result = rt >> sa;
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::dsrav(Registers& regs, u32 instr) { void Interpreter::dsrav(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s64 sa = rs & 63; s64 sa = rs & 63;
@@ -670,24 +670,24 @@ void Interpreter::dsrav(Registers& regs, u32 instr) {
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::dsra32(Registers& regs, u32 instr) { void Interpreter::dsra32(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s64 result = rt >> (sa + 32); s64 result = rt >> (sa + 32);
regs.gpr[RD(instr)] = result; regs.gpr[RD(instr)] = result;
} }
void Interpreter::jr(Registers& regs, u32 instr) { void Interpreter::jr(u32 instr) {
s64 address = regs.gpr[RS(instr)]; s64 address = regs.gpr[RS(instr)];
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC); FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
} }
branch(regs, true, address); branch(true, address);
} }
void Interpreter::dsub(Registers& regs, u32 instr) { void Interpreter::dsub(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s64 result = rs - rt; s64 result = rs - rt;
@@ -698,14 +698,14 @@ void Interpreter::dsub(Registers& regs, u32 instr) {
} }
} }
void Interpreter::dsubu(Registers& regs, u32 instr) { void Interpreter::dsubu(u32 instr) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u64 result = rs - rt; u64 result = rs - rt;
regs.gpr[RD(instr)] = s64(result); regs.gpr[RD(instr)] = s64(result);
} }
void Interpreter::sub(Registers& regs, u32 instr) { void Interpreter::sub(u32 instr) {
s32 rt = regs.gpr[RT(instr)]; s32 rt = regs.gpr[RT(instr)];
s32 rs = regs.gpr[RS(instr)]; s32 rs = regs.gpr[RS(instr)];
s32 result = rs - rt; s32 result = rs - rt;
@@ -716,14 +716,14 @@ void Interpreter::sub(Registers& regs, u32 instr) {
} }
} }
void Interpreter::subu(Registers& regs, u32 instr) { void Interpreter::subu(u32 instr) {
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
u32 rs = regs.gpr[RS(instr)]; u32 rs = regs.gpr[RS(instr)];
u32 result = rs - rt; u32 result = rs - rt;
regs.gpr[RD(instr)] = (s64)((s32)result); regs.gpr[RD(instr)] = (s64)((s32)result);
} }
void Interpreter::dmultu(Registers& regs, u32 instr) { void Interpreter::dmultu(u32 instr) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u128 result = (u128)rt * (u128)rs; u128 result = (u128)rt * (u128)rs;
@@ -731,7 +731,7 @@ void Interpreter::dmultu(Registers& regs, u32 instr) {
regs.hi = (s64)(result >> 64); regs.hi = (s64)(result >> 64);
} }
void Interpreter::dmult(Registers& regs, u32 instr) { void Interpreter::dmult(u32 instr) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s128 result = (s128)rt * (s128)rs; s128 result = (s128)rt * (s128)rs;
@@ -739,7 +739,7 @@ void Interpreter::dmult(Registers& regs, u32 instr) {
regs.hi = result >> 64; regs.hi = result >> 64;
} }
void Interpreter::multu(Registers& regs, u32 instr) { void Interpreter::multu(u32 instr) {
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
u32 rs = regs.gpr[RS(instr)]; u32 rs = regs.gpr[RS(instr)];
u64 result = (u64)rt * (u64)rs; u64 result = (u64)rt * (u64)rs;
@@ -747,7 +747,7 @@ void Interpreter::multu(Registers& regs, u32 instr) {
regs.hi = (s64)((s32)(result >> 32)); regs.hi = (s64)((s32)(result >> 32));
} }
void Interpreter::mult(Registers& regs, u32 instr) { void Interpreter::mult(u32 instr) {
s32 rt = regs.gpr[RT(instr)]; s32 rt = regs.gpr[RT(instr)];
s32 rs = regs.gpr[RS(instr)]; s32 rs = regs.gpr[RS(instr)];
s64 result = (s64)rt * (s64)rs; s64 result = (s64)rt * (s64)rs;
@@ -755,50 +755,50 @@ void Interpreter::mult(Registers& regs, u32 instr) {
regs.hi = (s64)((s32)(result >> 32)); regs.hi = (s64)((s32)(result >> 32));
} }
void Interpreter::mflo(Registers& regs, u32 instr) { void Interpreter::mflo(u32 instr) {
regs.gpr[RD(instr)] = regs.lo; regs.gpr[RD(instr)] = regs.lo;
} }
void Interpreter::mfhi(Registers& regs, u32 instr) { void Interpreter::mfhi(u32 instr) {
regs.gpr[RD(instr)] = regs.hi; regs.gpr[RD(instr)] = regs.hi;
} }
void Interpreter::mtlo(Registers& regs, u32 instr) { void Interpreter::mtlo(u32 instr) {
regs.lo = regs.gpr[RS(instr)]; regs.lo = regs.gpr[RS(instr)];
} }
void Interpreter::mthi(Registers& regs, u32 instr) { void Interpreter::mthi(u32 instr) {
regs.hi = regs.gpr[RS(instr)]; regs.hi = regs.gpr[RS(instr)];
} }
void Interpreter::trap(Registers& regs, bool cond) { void Interpreter::trap(bool cond) {
if(cond) { if(cond) {
FireException(regs, ExceptionCode::Trap, 0, regs.oldPC); FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
} }
} }
void Interpreter::mtc2(Registers& regs, u32 instr) { void Interpreter::mtc2(u32 instr) {
cop2Latch = regs.gpr[RT(instr)]; cop2Latch = regs.gpr[RT(instr)];
} }
void Interpreter::mfc2(Registers& regs, u32 instr) { void Interpreter::mfc2(u32 instr) {
s32 value = cop2Latch; s32 value = cop2Latch;
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void Interpreter::dmtc2(Registers& regs, u32 instr) { void Interpreter::dmtc2(u32 instr) {
cop2Latch = regs.gpr[RT(instr)]; cop2Latch = regs.gpr[RT(instr)];
} }
void Interpreter::dmfc2(Registers& regs, u32 instr) { void Interpreter::dmfc2(u32 instr) {
regs.gpr[RT(instr)] = cop2Latch; regs.gpr[RT(instr)] = cop2Latch;
} }
void Interpreter::ctc2(Registers& regs, u32) { void Interpreter::ctc2(u32) {
} }
void Interpreter::cfc2(Registers& regs, u32) { void Interpreter::cfc2(u32) {
} }

View File

@@ -35,10 +35,10 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, true); break; case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, true); break;
case 0x08: case 0x08:
switch(mask_branch) { switch(mask_branch) {
case 0: cpu.b(regs, instr, !regs.cop1.fcr31.compare); break; case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break;
case 1: cpu.b(regs, instr, regs.cop1.fcr31.compare); break; case 1: cpu.b(instr, regs.cop1.fcr31.compare); break;
case 2: cpu.bl(regs, instr, !regs.cop1.fcr31.compare); break; case 2: cpu.bl(instr, !regs.cop1.fcr31.compare); break;
case 3: cpu.bl(regs, instr, regs.cop1.fcr31.compare); break; case 3: cpu.bl(instr, regs.cop1.fcr31.compare); break;
default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch); default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
} }
break; break;

View File

@@ -86,6 +86,7 @@ inline void swc2(RSP& rsp, u32 instr) {
case 0x04: rsp.sqv(instr); break; case 0x04: rsp.sqv(instr); break;
case 0x06: rsp.spv(instr); break; case 0x06: rsp.spv(instr); break;
case 0x07: rsp.suv(instr); break; case 0x07: rsp.suv(instr); break;
case 0x09: rsp.sfv(instr); break;
case 0x0A: rsp.swv(instr); break; case 0x0A: rsp.swv(instr); break;
case 0x0B: rsp.stv(instr); break; case 0x0B: rsp.stv(instr); break;
default: Util::panic("Unhandled RSP SWC2 {:05b}\n", mask); default: Util::panic("Unhandled RSP SWC2 {:05b}\n", mask);

View File

@@ -420,6 +420,68 @@ void RSP::spv(u32 instr) {
} }
} }
void RSP::sfv(u32 instr) {
VPR& vt = vpr[VT(instr)];
u32 address = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 4);
int base = address & 7;
address &= ~7;
int e = E1(instr);
u8 values[4] = {0, 0, 0, 0};
switch (e) {
case 0:
case 15:
values[0] = vt.element[ELEMENT_INDEX(0)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(1)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(2)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(3)] >> 7;
break;
case 1:
values[0] = vt.element[ELEMENT_INDEX(6)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(7)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(4)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(5)] >> 7;
break;
case 4:
values[0] = vt.element[ELEMENT_INDEX(1)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(2)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(3)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(0)] >> 7;
break;
case 5:
values[0] = vt.element[ELEMENT_INDEX(7)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(4)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(5)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(6)] >> 7;
break;
case 8:
values[0] = vt.element[ELEMENT_INDEX(4)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(5)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(6)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(7)] >> 7;
break;
case 11:
values[0] = vt.element[ELEMENT_INDEX(3)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(0)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(1)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(2)] >> 7;
break;
case 12:
values[0] = vt.element[ELEMENT_INDEX(5)] >> 7;
values[1] = vt.element[ELEMENT_INDEX(6)] >> 7;
values[2] = vt.element[ELEMENT_INDEX(7)] >> 7;
values[3] = vt.element[ELEMENT_INDEX(4)] >> 7;
break;
default:
break;
}
for (int i = 0; i < 4; i++) {
WriteByte(address + ((base + (i << 2)) & 15), values[i]);
}
}
void RSP::sbv(u32 instr) { void RSP::sbv(u32 instr) {
int e = E1(instr); int e = E1(instr);
u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 0); u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 0);

View File

@@ -65,6 +65,13 @@ Settings::Settings(n64::Core& core) {
settingsFile << settings; settingsFile << settings;
} }
settingsFile.close(); settingsFile.close();
switch(core.cpuType) {
case n64::CpuType::Interpreter: core.cpuInterp = new n64::Interpreter; break;
case n64::CpuType::Dynarec: core.cpuDynarec = new n64::JIT::Dynarec; break;
case n64::CpuType::NONE:
Util::panic("BRUH\n");
}
} }
Settings::~Settings() { Settings::~Settings() {
@@ -100,7 +107,7 @@ void Settings::RenderWidget(bool& show) {
const char *categories[] = {"General", "CPU", "Audio"}; const char *categories[] = {"General", "CPU", "Audio"};
enum Category { General, CPU, Audio }; enum Category { General, CPU, Audio };
static int category = General; static int category = General;
CreateComboList("", &category, categories, 3); CreateComboList("##", &category, categories, 3);
ImGui::Separator(); ImGui::Separator();
switch (category) { switch (category) {
case General: case General:

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#define SDL_MAIN_HANDLED
#include <ParallelRDPWrapper.hpp> #include <ParallelRDPWrapper.hpp>
#include <imgui.h> #include <imgui.h>
#include <imgui_impl_sdl.h> #include <imgui_impl_sdl.h>

View File

@@ -1,10 +1,6 @@
#include <App.hpp> #include <App.hpp>
#include <MupenMovie.hpp> #include <MupenMovie.hpp>
#ifdef _WIN32
#define main SDL_main
#endif
int main(int argc, char** argv) { int main(int argc, char** argv) {
App* app = new App; App* app = new App;
if(argc > 1) { if(argc > 1) {

View File

@@ -91,7 +91,7 @@ inline void* aligned_alloc(size_t alignment, size_t size) {
return _aligned_malloc(size, alignment); return _aligned_malloc(size, alignment);
} }
inline void free(void* ptr) { inline void aligned_free(void* ptr) {
_aligned_free(ptr); _aligned_free(ptr);
} }
#else #else
@@ -99,7 +99,7 @@ inline void* aligned_alloc(size_t alignment, size_t size) {
return std::aligned_alloc(alignment, size); return std::aligned_alloc(alignment, size);
} }
inline void free(void* ptr) { inline void aligned_free(void* ptr) {
std::free(ptr); std::free(ptr);
} }
#endif #endif