Let's try doing this again
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Core;
|
struct Core;
|
||||||
struct Interpreter final : BaseCPU {
|
struct Interpreter : BaseCPU {
|
||||||
explicit Interpreter(ParallelRDP&);
|
explicit Interpreter(ParallelRDP&);
|
||||||
~Interpreter() override = default;
|
~Interpreter() override = default;
|
||||||
int Step() override;
|
int Step() override;
|
||||||
|
|||||||
84
src/backend/core/JIT.cpp
Normal file
84
src/backend/core/JIT.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#include <Core.hpp>
|
||||||
|
#include <jit/helpers.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
JIT::JIT(ParallelRDP& parallel) : mem(regs, parallel) { }
|
||||||
|
|
||||||
|
bool JIT::ShouldServiceInterrupt() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::CheckCompareInterrupt() {
|
||||||
|
regs.cop0.count++;
|
||||||
|
regs.cop0.count &= 0x1FFFFFFFF;
|
||||||
|
if(regs.cop0.count == (u64)regs.cop0.compare << 1) {
|
||||||
|
regs.cop0.cause.ip7 = 1;
|
||||||
|
mem.mmio.mi.UpdateInterrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int JIT::Step() {
|
||||||
|
CheckCompareInterrupt();
|
||||||
|
|
||||||
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
|
regs.delaySlot = false;
|
||||||
|
|
||||||
|
if (check_address_error(0b11, u64(regs.pc))) [[unlikely]] {
|
||||||
|
regs.cop0.HandleTLBException(regs.pc);
|
||||||
|
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.pc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 paddr = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction = mem.Read<u32>(regs, paddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ShouldServiceInterrupt()) {
|
||||||
|
regs.cop0.FireException(ExceptionCode::Interrupt, 0, regs.pc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.oldPC = regs.pc;
|
||||||
|
regs.pc = regs.nextPC;
|
||||||
|
regs.nextPC += 4;
|
||||||
|
|
||||||
|
Exec(instruction);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> JIT::Serialize() {
|
||||||
|
std::vector<u8> res{};
|
||||||
|
|
||||||
|
res.resize(sizeof(Registers));
|
||||||
|
|
||||||
|
memcpy(res.data(), ®s, sizeof(Registers));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JIT::Deserialize(const std::vector<u8> &data) {
|
||||||
|
memcpy(®s, data.data(), sizeof(Registers));
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/backend/core/JIT.hpp
Normal file
132
src/backend/core/JIT.hpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Mem.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <BaseCPU.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
struct Core;
|
||||||
|
struct JIT : BaseCPU {
|
||||||
|
explicit JIT(ParallelRDP&);
|
||||||
|
~Interpreter() override = default;
|
||||||
|
int Step() override;
|
||||||
|
void Reset() override {
|
||||||
|
regs.Reset();
|
||||||
|
mem.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem& GetMem() override {
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
Registers& GetRegs() override {
|
||||||
|
return regs;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Registers regs;
|
||||||
|
Mem mem;
|
||||||
|
u64 cop2Latch{};
|
||||||
|
friend struct Cop1;
|
||||||
|
#define check_address_error(mask, vaddr) (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
||||||
|
bool ShouldServiceInterrupt() override;
|
||||||
|
void CheckCompareInterrupt() override;
|
||||||
|
std::vector<u8> Serialize() override;
|
||||||
|
void Deserialize(const std::vector<u8>&) override;
|
||||||
|
|
||||||
|
void cop2Decode(u32);
|
||||||
|
void special(u32);
|
||||||
|
void regimm(u32);
|
||||||
|
void Exec(u32);
|
||||||
|
void add(u32);
|
||||||
|
void addu(u32);
|
||||||
|
void addi(u32);
|
||||||
|
void addiu(u32);
|
||||||
|
void andi(u32);
|
||||||
|
void and_(u32);
|
||||||
|
void branch(bool, s64);
|
||||||
|
void branch_likely(bool, s64);
|
||||||
|
void b(u32, bool);
|
||||||
|
void blink(u32, bool);
|
||||||
|
void bl(u32, bool);
|
||||||
|
void bllink(u32, bool);
|
||||||
|
void dadd(u32);
|
||||||
|
void daddu(u32);
|
||||||
|
void daddi(u32);
|
||||||
|
void daddiu(u32);
|
||||||
|
void ddiv(u32);
|
||||||
|
void ddivu(u32);
|
||||||
|
void div(u32);
|
||||||
|
void divu(u32);
|
||||||
|
void dmult(u32);
|
||||||
|
void dmultu(u32);
|
||||||
|
void dsll(u32);
|
||||||
|
void dsllv(u32);
|
||||||
|
void dsll32(u32);
|
||||||
|
void dsra(u32);
|
||||||
|
void dsrav(u32);
|
||||||
|
void dsra32(u32);
|
||||||
|
void dsrl(u32);
|
||||||
|
void dsrlv(u32);
|
||||||
|
void dsrl32(u32);
|
||||||
|
void dsub(u32);
|
||||||
|
void dsubu(u32);
|
||||||
|
void j(u32);
|
||||||
|
void jr(u32);
|
||||||
|
void jal(u32);
|
||||||
|
void jalr(u32);
|
||||||
|
void lui(u32);
|
||||||
|
void lbu(u32);
|
||||||
|
void lb(u32);
|
||||||
|
void ld(u32);
|
||||||
|
void ldl(u32);
|
||||||
|
void ldr(u32);
|
||||||
|
void lh(u32);
|
||||||
|
void lhu(u32);
|
||||||
|
void ll(u32);
|
||||||
|
void lld(u32);
|
||||||
|
void lw(u32);
|
||||||
|
void lwl(u32);
|
||||||
|
void lwu(u32);
|
||||||
|
void lwr(u32);
|
||||||
|
void mfhi(u32);
|
||||||
|
void mflo(u32);
|
||||||
|
void mult(u32);
|
||||||
|
void multu(u32);
|
||||||
|
void mthi(u32);
|
||||||
|
void mtlo(u32);
|
||||||
|
void nor(u32);
|
||||||
|
void sb(u32);
|
||||||
|
void sc(u32);
|
||||||
|
void scd(u32);
|
||||||
|
void sd(u32);
|
||||||
|
void sdl(u32);
|
||||||
|
void sdr(u32);
|
||||||
|
void sh(u32);
|
||||||
|
void sw(u32);
|
||||||
|
void swl(u32);
|
||||||
|
void swr(u32);
|
||||||
|
void slti(u32);
|
||||||
|
void sltiu(u32);
|
||||||
|
void slt(u32);
|
||||||
|
void sltu(u32);
|
||||||
|
void sll(u32);
|
||||||
|
void sllv(u32);
|
||||||
|
void sub(u32);
|
||||||
|
void subu(u32);
|
||||||
|
void sra(u32);
|
||||||
|
void srav(u32);
|
||||||
|
void srl(u32);
|
||||||
|
void srlv(u32);
|
||||||
|
void trap(bool);
|
||||||
|
void or_(u32);
|
||||||
|
void ori(u32);
|
||||||
|
void xor_(u32);
|
||||||
|
void xori(u32);
|
||||||
|
|
||||||
|
void mtc2(u32);
|
||||||
|
void mfc2(u32);
|
||||||
|
void dmtc2(u32);
|
||||||
|
void dmfc2(u32);
|
||||||
|
void ctc2(u32);
|
||||||
|
void cfc2(u32);
|
||||||
|
};
|
||||||
|
}
|
||||||
23
src/backend/core/jit/helpers.hpp
Normal file
23
src/backend/core/jit/helpers.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include <CpuDefinitions.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
static inline bool SpecialEndsBlock(u32 instr) {
|
||||||
|
u8 mask = instr & 0x3F;
|
||||||
|
switch (mask) {
|
||||||
|
case JR: case JALR: case SYSCALL: case BREAK:
|
||||||
|
case TGE: case TGEU: case TLT: case TLTU:
|
||||||
|
case TEQ: case TNE: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool InstrEndsBlock(u32 instr) {
|
||||||
|
u8 mask = (instr >> 26) & 0x3f;
|
||||||
|
switch (mask) {
|
||||||
|
case SPECIAL: return SpecialEndsBlock(instr);
|
||||||
|
case REGIMM: case J: case JAL: case BEQ:
|
||||||
|
case BNE: case BLEZ: case BGTZ: case BEQL:
|
||||||
|
case BNEL: case BLEZL: case BGTZL: return true:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,9 @@ struct Registers {
|
|||||||
void Reset();
|
void Reset();
|
||||||
void SetPC64(s64);
|
void SetPC64(s64);
|
||||||
void SetPC32(s32);
|
void SetPC32(s32);
|
||||||
|
|
||||||
s64 gpr[32]{};
|
s64 gpr[32]{};
|
||||||
|
bool gprIsConstant[32]{};
|
||||||
Cop0 cop0;
|
Cop0 cop0;
|
||||||
Cop1 cop1;
|
Cop1 cop1;
|
||||||
s64 oldPC{}, pc{}, nextPC{};
|
s64 oldPC{}, pc{}, nextPC{};
|
||||||
|
|||||||
Reference in New Issue
Block a user