Lay down initial JIT structure

This commit is contained in:
SimoneN64
2023-07-25 10:53:23 +02:00
parent fcee7f5850
commit 4715652970
7 changed files with 175 additions and 11 deletions

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> #include <SDL2/SDL_events.h>
#include <backend/core/Interpreter.hpp> #include <backend/core/Interpreter.hpp>
#include <backend/core/JIT.hpp>
#include <string> #include <string>
#include <SDL2/SDL_timer.h> #include <SDL2/SDL_timer.h>

View File

@@ -6,7 +6,12 @@ namespace n64 {
struct BaseCPU { struct BaseCPU {
virtual ~BaseCPU() = default; virtual ~BaseCPU() = default;
virtual int Step() {return 0;} virtual int Step() {return 0;}
virtual void Reset() {} virtual void Reset() {
regs.Reset();
mem.Reset();
}
virtual bool ShouldServiceInterrupt() {return false;}
virtual void CheckCompareInterrupt() {}
Registers regs; Registers regs;
Mem mem; Mem mem;
}; };

View File

@@ -1,11 +1,6 @@
#include <Core.hpp> #include <Core.hpp>
namespace n64 { namespace n64 {
void Interpreter::Reset() {
regs.Reset();
mem.Reset();
}
int Interpreter::Step() { int Interpreter::Step() {
CheckCompareInterrupt(); CheckCompareInterrupt();

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <Mem.hpp> #include <Mem.hpp>
#include <vector> #include <vector>
#include "BaseCPU.hpp" #include <BaseCPU.hpp>
namespace n64 { namespace n64 {
struct Core; struct Core;
@@ -9,12 +9,11 @@ struct Interpreter : BaseCPU {
Interpreter() = default; Interpreter() = default;
~Interpreter() override = default; ~Interpreter() override = default;
int Step() override; int Step() override;
void Reset() override;
private: private:
u64 cop2Latch{}; u64 cop2Latch{};
friend struct Cop1; friend struct Cop1;
[[nodiscard]] FORCE_INLINE bool ShouldServiceInterrupt() const { [[nodiscard]] FORCE_INLINE bool ShouldServiceInterrupt() override {
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
bool interrupts_enabled = regs.cop0.status.ie == 1; bool interrupts_enabled = regs.cop0.status.ie == 1;
bool currently_handling_exception = regs.cop0.status.exl == 1; bool currently_handling_exception = regs.cop0.status.exl == 1;
@@ -24,7 +23,7 @@ private:
!currently_handling_exception && !currently_handling_error; !currently_handling_exception && !currently_handling_error;
} }
FORCE_INLINE void CheckCompareInterrupt() { FORCE_INLINE void CheckCompareInterrupt() override {
regs.cop0.count++; regs.cop0.count++;
regs.cop0.count &= 0x1FFFFFFFF; regs.cop0.count &= 0x1FFFFFFFF;
if(regs.cop0.count == (u64)regs.cop0.compare << 1) { if(regs.cop0.count == (u64)regs.cop0.compare << 1) {

47
src/backend/core/JIT.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include <JIT.hpp>
namespace n64 {
using namespace Xbyak;
JIT::JIT() : CodeGenerator(0x80000) { }
void JIT::Reset() {
reset();
regs.Reset();
mem.Reset();
}
bool JIT::ShouldServiceInterrupt() {
}
void JIT::CheckCompareInterrupt() {
}
int JIT::Step() {
CheckCompareInterrupt();
regs.prevDelaySlot = regs.delaySlot;
regs.delaySlot = false;
u32 paddr = 0;
if(!MapVAddr(regs, LOAD, regs.pc, paddr)) {
HandleTLBException(regs, regs.pc);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
return 0;
}
u32 instruction = mem.Read32(regs, paddr);
if(ShouldServiceInterrupt()) {
FireException(regs, ExceptionCode::Interrupt, 0, false);
return 0;
}
regs.oldPC = regs.pc;
regs.pc = regs.nextPC;
regs.nextPC += 4;
return 1;
}
}

117
src/backend/core/JIT.hpp Normal file
View File

@@ -0,0 +1,117 @@
#pragma once
#include <Mem.hpp>
#include <vector>
#include <BaseCPU.hpp>
#include <xbyak.h>
namespace n64 {
using Fn = void(*)();
struct JIT : BaseCPU, Xbyak::CodeGenerator {
JIT();
~JIT() override = default;
int Step() override;
void Reset() override;
private:
bool ShouldServiceInterrupt() override;
void CheckCompareInterrupt() override;
Fn* blocks[0x80000]{};
void cop2Decode(u32);
void special(u32);
void regimm(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);
};
}

View File

@@ -53,7 +53,7 @@ Settings::Settings(n64::Core& core) {
} }
if(jit) { if(jit) {
Util::panic("JIT is unimplemented!"); core.cpu = std::make_unique<n64::JIT>();
} else { } else {
core.cpu = std::make_unique<n64::Interpreter>(); core.cpu = std::make_unique<n64::Interpreter>();
} }