Start implementing some instructions
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
#include <ParallelRDPWrapper.hpp>
|
#include <ParallelRDPWrapper.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
Core::Core(ParallelRDP& parallel) : cpu(std::make_unique<Interpreter>(parallel)) {}
|
Core::Core(ParallelRDP& parallel) : cpu(std::make_unique<JIT>(parallel)) {}
|
||||||
|
|
||||||
void Core::Stop() {
|
void Core::Stop() {
|
||||||
render = false;
|
render = false;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <backend/core/Interpreter.hpp>
|
#include <backend/core/Interpreter.hpp>
|
||||||
|
#include <backend/core/JIT.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct Window;
|
struct Window;
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ file(GLOB SOURCES *.cpp)
|
|||||||
file(GLOB HEADERS *.hpp)
|
file(GLOB HEADERS *.hpp)
|
||||||
|
|
||||||
add_subdirectory(interpreter)
|
add_subdirectory(interpreter)
|
||||||
|
add_subdirectory(jit)
|
||||||
add_subdirectory(mem)
|
add_subdirectory(mem)
|
||||||
add_subdirectory(mmio)
|
add_subdirectory(mmio)
|
||||||
add_subdirectory(registers)
|
add_subdirectory(registers)
|
||||||
add_subdirectory(rsp)
|
add_subdirectory(rsp)
|
||||||
|
|
||||||
add_library(core ${SOURCES} ${HEADERS})
|
add_library(core ${SOURCES} ${HEADERS})
|
||||||
target_link_libraries(core PRIVATE interpreter mem mmio unarr registers rsp)
|
target_link_libraries(core PRIVATE jit interpreter mem mmio unarr registers rsp)
|
||||||
@@ -2,7 +2,10 @@
|
|||||||
#include <jit/helpers.hpp>
|
#include <jit/helpers.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
JIT::JIT(ParallelRDP& parallel) : mem(regs, parallel) { }
|
JIT::JIT(ParallelRDP& parallel) : mem(regs, parallel) {
|
||||||
|
regs.gpr[0] = 0;
|
||||||
|
regs.gprIsConstant[0] = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool JIT::ShouldServiceInterrupt() {
|
bool JIT::ShouldServiceInterrupt() {
|
||||||
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
|
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
|
||||||
@@ -24,46 +27,40 @@ void JIT::CheckCompareInterrupt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int JIT::Step() {
|
int JIT::Step() {
|
||||||
CheckCompareInterrupt();
|
u32 instruction;
|
||||||
|
s64 pc = regs.pc;
|
||||||
|
|
||||||
regs.prevDelaySlot = regs.delaySlot;
|
do {
|
||||||
regs.delaySlot = false;
|
//CheckCompareInterrupt();
|
||||||
|
|
||||||
if (check_address_error(0b11, u64(regs.pc))) [[unlikely]] {
|
//regs.prevDelaySlot = regs.delaySlot;
|
||||||
regs.cop0.HandleTLBException(regs.pc);
|
//regs.delaySlot = false;
|
||||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.pc);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 paddr = 0;
|
/*if (check_address_error(0b11, u64(pc))) [[unlikely]] {
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, paddr)) {
|
regs.cop0.HandleTLBException(pc);
|
||||||
regs.cop0.HandleTLBException(regs.pc);
|
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, pc);
|
||||||
regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 instruction = mem.Read<u32>(regs, paddr);
|
|
||||||
while (!InstrEndsBlock(instr)) {
|
|
||||||
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, paddr)) {
|
|
||||||
regs.cop0.HandleTLBException(regs.pc);
|
|
||||||
regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc);
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
u32 paddr = 0;
|
||||||
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, pc, paddr)) {
|
||||||
|
/*regs.cop0.HandleTLBException(pc);
|
||||||
|
regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, pc);
|
||||||
|
return 1;*/
|
||||||
|
Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!", regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD));
|
||||||
}
|
}
|
||||||
|
|
||||||
instruction = mem.Read<u32>(regs, paddr);
|
instruction = mem.Read<u32>(regs, paddr);
|
||||||
}
|
|
||||||
|
|
||||||
if(ShouldServiceInterrupt()) {
|
/*if(ShouldServiceInterrupt()) {
|
||||||
regs.cop0.FireException(ExceptionCode::Interrupt, 0, regs.pc);
|
regs.cop0.FireException(ExceptionCode::Interrupt, 0, regs.pc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
regs.oldPC = regs.pc;
|
pc += 4;
|
||||||
regs.pc = regs.nextPC;
|
|
||||||
regs.nextPC += 4;
|
|
||||||
|
|
||||||
Exec(instruction);
|
//Exec(instruction);
|
||||||
|
} while (!InstrEndsBlock(instruction));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ private:
|
|||||||
std::vector<u8> Serialize() override;
|
std::vector<u8> Serialize() override;
|
||||||
void Deserialize(const std::vector<u8>&) override;
|
void Deserialize(const std::vector<u8>&) override;
|
||||||
|
|
||||||
|
void Emit(u32);
|
||||||
void cop2Decode(u32);
|
void cop2Decode(u32);
|
||||||
void special(u32);
|
void special(u32);
|
||||||
void regimm(u32);
|
void regimm(u32);
|
||||||
void Exec(u32);
|
|
||||||
void add(u32);
|
void add(u32);
|
||||||
void addu(u32);
|
void addu(u32);
|
||||||
void addi(u32);
|
void addi(u32);
|
||||||
|
|||||||
4
src/backend/core/jit/CMakeLists.txt
Normal file
4
src/backend/core/jit/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
file(GLOB_RECURSE SOURCES *.cpp)
|
||||||
|
file(GLOB_RECURSE HEADERS *.hpp)
|
||||||
|
|
||||||
|
add_library(jit ${SOURCES} ${HEADERS})
|
||||||
@@ -17,7 +17,8 @@ static inline bool InstrEndsBlock(u32 instr) {
|
|||||||
case SPECIAL: return SpecialEndsBlock(instr);
|
case SPECIAL: return SpecialEndsBlock(instr);
|
||||||
case REGIMM: case J: case JAL: case BEQ:
|
case REGIMM: case J: case JAL: case BEQ:
|
||||||
case BNE: case BLEZ: case BGTZ: case BEQL:
|
case BNE: case BLEZ: case BGTZ: case BEQL:
|
||||||
case BNEL: case BLEZL: case BGTZL: return true:
|
case BNEL: case BLEZL: case BGTZL: return true;
|
||||||
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
317
src/backend/core/jit/instructions.cpp
Normal file
317
src/backend/core/jit/instructions.cpp
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
#include <JIT.hpp>
|
||||||
|
|
||||||
|
#define check_signed_overflow(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 {
|
||||||
|
void JIT::lui(u32 instr) {
|
||||||
|
u64 val = s64((s16)instr);
|
||||||
|
val <<= 16;
|
||||||
|
if (RT(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RT(instr)] = val;
|
||||||
|
regs.gprIsConstant[RT(instr)] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::add(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
u32 rs = (s32)regs.gpr[RS(instr)];
|
||||||
|
u32 rt = (s32)regs.gpr[RT(instr)];
|
||||||
|
u32 result = rs + rt;
|
||||||
|
if(check_signed_overflow(rs, rt, result)) {
|
||||||
|
//regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||||
|
Util::panic("[JIT]: Unhandled Overflow exception in ADD!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RD(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RD(instr)] = s32(result);
|
||||||
|
regs.gprIsConstant[RD(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant ADD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::addu(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
s32 rs = (s32) regs.gpr[RS(instr)];
|
||||||
|
s32 rt = (s32) regs.gpr[RT(instr)];
|
||||||
|
s32 result = rs + rt;
|
||||||
|
|
||||||
|
if (RD(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RD(instr)] = result;
|
||||||
|
regs.gprIsConstant[RD(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant ADDI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::addi(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr))) {
|
||||||
|
u32 rs = regs.gpr[RS(instr)];
|
||||||
|
u32 imm = s32(s16(instr));
|
||||||
|
u32 result = rs + imm;
|
||||||
|
if(check_signed_overflow(rs, imm, result)) {
|
||||||
|
Util::panic("[JIT]: Unhandled Overflow exception in ADDI!");
|
||||||
|
} else {
|
||||||
|
if (RT(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RT(instr)] = s32(result);
|
||||||
|
regs.gprIsConstant[RT(instr)] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant ADDI!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::addiu(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr))) {
|
||||||
|
u32 rs = regs.gpr[RS(instr)];
|
||||||
|
u32 imm = s32(s16(instr));
|
||||||
|
u32 result = rs + imm;
|
||||||
|
|
||||||
|
if (RT(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RT(instr)] = s32(result);
|
||||||
|
regs.gprIsConstant[RT(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant ADDIU!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::andi(u32 instr) {
|
||||||
|
s64 imm = (u16)instr;
|
||||||
|
if(regs.IsRegConstant(RS(instr))) {
|
||||||
|
if (RT(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm;
|
||||||
|
regs.gprIsConstant[RT(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant ANDI!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::and_(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
if (RD(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)];
|
||||||
|
regs.gprIsConstant[RD(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant AND!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dadd(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
u64 rs = regs.gpr[RS(instr)];
|
||||||
|
u64 rt = regs.gpr[RT(instr)];
|
||||||
|
u64 result = rt + rs;
|
||||||
|
if (check_signed_overflow(rs, rt, result)) {
|
||||||
|
//regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||||
|
Util::panic("[JIT]: Unhandled Overflow exception in DADD!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RD(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RD(instr)] = result;
|
||||||
|
regs.gprIsConstant[RD(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DADD!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::daddu(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
if (RD(instr) != 0) [[likely]] {
|
||||||
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
|
regs.gpr[RD(instr)] = rt + rs;
|
||||||
|
regs.gprIsConstant[RD(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DADD!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::daddi(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr))) {
|
||||||
|
u64 imm = s64(s16(instr));
|
||||||
|
u64 rs = regs.gpr[RS(instr)];
|
||||||
|
u64 result = imm + rs;
|
||||||
|
if (check_signed_overflow(rs, imm, result)) {
|
||||||
|
//regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||||
|
Util::panic("[JIT]: Unhandled Overflow exception in DADDI!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RT(instr) != 0) [[likely]] {
|
||||||
|
regs.gpr[RT(instr)] = result;
|
||||||
|
regs.gprIsConstant[RT(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DADDI!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::daddiu(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr))) {
|
||||||
|
if (RT(instr) != 0) [[likely]] {
|
||||||
|
s16 imm = s16(instr);
|
||||||
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
|
regs.gpr[RT(instr)] = imm + rs;
|
||||||
|
regs.gprIsConstant[RT(instr)] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DADDI!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::ddiv(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
s64 dividend = regs.gpr[RS(instr)];
|
||||||
|
s64 divisor = regs.gpr[RT(instr)];
|
||||||
|
if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) {
|
||||||
|
regs.lo = dividend;
|
||||||
|
regs.hi = 0;
|
||||||
|
} else if(divisor == 0) {
|
||||||
|
regs.hi = dividend;
|
||||||
|
if(dividend >= 0) {
|
||||||
|
regs.lo = -1;
|
||||||
|
} else {
|
||||||
|
regs.lo = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s64 quotient = dividend / divisor;
|
||||||
|
s64 remainder = dividend % divisor;
|
||||||
|
regs.lo = quotient;
|
||||||
|
regs.hi = remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.loIsConstant = true;
|
||||||
|
regs.hiIsConstant = true;
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DDIV!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::ddivu(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
u64 dividend = regs.gpr[RS(instr)];
|
||||||
|
u64 divisor = regs.gpr[RT(instr)];
|
||||||
|
if (divisor == 0) {
|
||||||
|
regs.lo = -1;
|
||||||
|
regs.hi = (s64) dividend;
|
||||||
|
} else {
|
||||||
|
u64 quotient = dividend / divisor;
|
||||||
|
u64 remainder = dividend % divisor;
|
||||||
|
regs.lo = (s64) quotient;
|
||||||
|
regs.hi = (s64) remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.loIsConstant = true;
|
||||||
|
regs.hiIsConstant = true;
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DDIVU!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::div(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
s64 dividend = (s32) regs.gpr[RS(instr)];
|
||||||
|
s64 divisor = (s32) regs.gpr[RT(instr)];
|
||||||
|
|
||||||
|
if (divisor == 0) {
|
||||||
|
regs.hi = dividend;
|
||||||
|
if (dividend >= 0) {
|
||||||
|
regs.lo = s64(-1);
|
||||||
|
} else {
|
||||||
|
regs.lo = s64(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s32 quotient = dividend / divisor;
|
||||||
|
s32 remainder = dividend % divisor;
|
||||||
|
regs.lo = quotient;
|
||||||
|
regs.hi = remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.loIsConstant = true;
|
||||||
|
regs.hiIsConstant = true;
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DIV!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::divu(u32 instr) {
|
||||||
|
if(regs.IsRegConstant(RS(instr), RT(instr))) {
|
||||||
|
u32 dividend = regs.gpr[RS(instr)];
|
||||||
|
u32 divisor = regs.gpr[RT(instr)];
|
||||||
|
if (divisor == 0) {
|
||||||
|
regs.lo = -1;
|
||||||
|
regs.hi = (s32) dividend;
|
||||||
|
} else {
|
||||||
|
s32 quotient = (s32) (dividend / divisor);
|
||||||
|
s32 remainder = (s32) (dividend % divisor);
|
||||||
|
regs.lo = quotient;
|
||||||
|
regs.hi = remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.loIsConstant = true;
|
||||||
|
regs.hiIsConstant = true;
|
||||||
|
} else {
|
||||||
|
Util::panic("[JIT]: Implement non constant DIVU!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dmult(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dmultu(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsll(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsllv(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsll32(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsra(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsrav(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsra32(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsrl(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsrlv(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsrl32(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsub(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::dsubu(u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,9 +7,20 @@ struct Registers {
|
|||||||
void Reset();
|
void Reset();
|
||||||
void SetPC64(s64);
|
void SetPC64(s64);
|
||||||
void SetPC32(s32);
|
void SetPC32(s32);
|
||||||
|
|
||||||
|
bool IsRegConstant(u32 index) {
|
||||||
|
if(index == 0) return true;
|
||||||
|
return gprIsConstant[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
bool IsRegConstant(Args... indices) {
|
||||||
|
return IsRegConstant(indices...);
|
||||||
|
}
|
||||||
|
|
||||||
s64 gpr[32]{};
|
s64 gpr[32]{};
|
||||||
bool gprIsConstant[32]{};
|
bool gprIsConstant[32]{};
|
||||||
|
bool loIsConstant = false, hiIsConstant = false;
|
||||||
Cop0 cop0;
|
Cop0 cop0;
|
||||||
Cop1 cop1;
|
Cop1 cop1;
|
||||||
s64 oldPC{}, pc{}, nextPC{};
|
s64 oldPC{}, pc{}, nextPC{};
|
||||||
|
|||||||
Reference in New Issue
Block a user