#include #include #include namespace n64 { #ifdef KAIZEN_JIT_ENABLED Registers::Registers(JIT &jit) : jit(jit) { Reset(); } #else Registers::Registers() { stack_trace.resize(0x10000000); Reset(); } #endif void Registers::Reset() { hi = 0; lo = 0; delaySlot = false; prevDelaySlot = false; std::fill(stack_trace.begin(), stack_trace.end(), 0); gpr.fill(0); regIsConstant = 1; // first bit is true indicating $zero is constant which yes it is always cop0.Reset(); cop1.Reset(); steps = 0; extraCycles = 0; } void Registers::SetPC64(s64 val) { oldPC = pc; pc = val; nextPC = pc + 4; } void Registers::SetPC32(s32 val) { oldPC = pc; pc = s64(val); nextPC = pc + 4; } template <> u64 Registers::Read(size_t idx) { return gpr[idx]; } template <> s64 Registers::Read(const size_t idx) { return static_cast(Read(idx)); } template <> u32 Registers::Read(size_t idx) { return gpr[idx]; } template <> s32 Registers::Read(size_t idx) { return static_cast(Read(idx)); } template <> u16 Registers::Read(size_t idx) { return gpr[idx]; } template <> s16 Registers::Read(size_t idx) { return static_cast(Read(idx)); } template <> u8 Registers::Read(size_t idx) { return gpr[idx]; } template <> s8 Registers::Read(size_t idx) { return static_cast(Read(idx)); } #ifdef KAIZEN_JIT_ENABLED template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt64(), Read(idx)); return; } jit.code.mov(reg.cvt64(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt64(), Read(idx)); return; } jit.code.mov(reg.cvt64(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt32(), Read(idx)); return; } jit.code.mov(reg.cvt32(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt32(), Read(idx)); return; } jit.code.mov(reg.cvt32(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt16(), Read(idx)); return; } jit.code.mov(reg.cvt16(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt16(), Read(idx)); return; } jit.code.mov(reg.cvt16(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt8(), Read(idx)); return; } jit.code.mov(reg.cvt8(), jit.GPR(idx)); } template <> void Registers::Read(size_t idx, Xbyak::Reg reg) { if (IsRegConstant(idx)) { jit.code.mov(reg.cvt8(), Read(idx)); return; } jit.code.mov(reg.cvt8(), jit.GPR(idx)); } #endif template <> void Registers::Write(size_t idx, bool v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, u64 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, s64 v) { Write(idx, v); } template <> void Registers::Write(size_t idx, u32 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, s32 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, u16 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, s16 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, u8 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } template <> void Registers::Write(size_t idx, s8 v) { if (idx == 0) return; regIsConstant |= (1 << idx); gpr[idx] = v; } #ifdef KAIZEN_JIT_ENABLED template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; regIsConstant &= ~(1 << idx); jit.code.movsx(v.cvt64(), v.cvt8()); jit.code.mov(jit.GPR(idx), v); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; regIsConstant &= ~(1 << idx); jit.code.movsx(v.cvt64(), v.cvt8()); jit.code.mov(jit.GPR(idx), v); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; regIsConstant &= ~(1 << idx); jit.code.movzx(v.cvt64(), v.cvt8()); jit.code.mov(jit.GPR(idx), v.cvt64()); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; regIsConstant &= ~(1 << idx); jit.code.movsx(v.cvt64(), v.cvt16()); jit.code.mov(jit.GPR(idx), v.cvt64()); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; if (!jit) panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); regIsConstant &= ~(1 << idx); jit.code.movzx(v.cvt64(), v.cvt16()); jit.code.mov(jit.GPR(idx), v.cvt64()); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; if (!jit) panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); regIsConstant &= ~(1 << idx); jit.code.movsxd(v.cvt64(), v.cvt32()); jit.code.mov(jit.GPR(idx), v.cvt64()); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; if (!jit) panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); regIsConstant &= ~(1 << idx); jit.code.movzx(v.cvt64(), v.cvt32()); jit.code.mov(jit.GPR(idx), v.cvt64()); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { if (idx == 0) return; if (!jit) panic("Did you try to call Registers::Write(size_t, *Xbyak::Reg*) from the interpreter?"); regIsConstant &= ~(1 << idx); jit.code.mov(jit.GPR(idx), v.cvt64()); } template <> void Registers::Write(size_t idx, Xbyak::Reg v) { Write(idx, v); } #endif } // namespace n64