it's a start...
This commit is contained in:
@@ -88,6 +88,9 @@ void Core::StepRSP(const u32 cpuCycles) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpuType == CachedInterpreter)
|
||||
return mmio.rsp.ExecuteCached();
|
||||
|
||||
static constexpr u32 cpuRatio = 3, rspRatio = 2;
|
||||
|
||||
regs.steps += cpuCycles;
|
||||
|
||||
@@ -152,8 +152,6 @@ u32 Interpreter::ExecuteCached() {
|
||||
// 0, making so the emulator halts cause the outer loop won't advance
|
||||
const auto blockCycles = line->cycles;
|
||||
for (u32 i = 0; i < line->len; i++) {
|
||||
addr += 4;
|
||||
|
||||
if (!MaybeAdvance())
|
||||
return i + 1;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <Core.hpp>
|
||||
#include <log.hpp>
|
||||
#include <jit/helpers.hpp>
|
||||
|
||||
namespace n64 {
|
||||
RSP::RSP() { Reset(); }
|
||||
@@ -230,4 +231,70 @@ void RSP::Write(const u32 addr, const u32 val) {
|
||||
panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
void RSP::CacheBlock(u16 addr) {
|
||||
auto blockAddr = addr;
|
||||
|
||||
CachedLine line;
|
||||
u32 i;
|
||||
bool fetchDelaySlot = false;
|
||||
|
||||
for (i = 0; i < MAX_INSTR_PER_BLOCK; i++) {
|
||||
Instruction instr = ircolib::ReadAccess<u32>(imem, addr & IMEM_DSIZE);
|
||||
|
||||
addr += 4;
|
||||
line.code[i] = instr;
|
||||
|
||||
if (fetchDelaySlot) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (InstrEndsBlock(instr)) {
|
||||
if (InstrHasDelaySlot(instr) && !fetchDelaySlot) {
|
||||
fetchDelaySlot = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
i = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line.cycles = i;
|
||||
line.len = i;
|
||||
cachedState.blocks[CACHE_GET_BLOCK(blockAddr)]->lines[CACHE_GET_LINE(blockAddr)] = new CachedLine(line);
|
||||
|
||||
return ExecuteCached();
|
||||
}
|
||||
|
||||
void RSP::ExecuteCached() {
|
||||
u16 addr = pc;
|
||||
auto &blocks = cachedState.blocks;
|
||||
if (!blocks[CACHE_GET_BLOCK(addr)]) {
|
||||
blocks[CACHE_GET_BLOCK(addr)] = new CachedBlock<cachedState.MAX_LINES / 4>();
|
||||
return CacheBlock(addr);
|
||||
}
|
||||
|
||||
const auto line = blocks[CACHE_GET_BLOCK(addr)]->lines[CACHE_GET_LINE(addr)];
|
||||
if (line) {
|
||||
for (u32 i = 0; i < line->len; i++) {
|
||||
prevDelaySlot = delaySlot;
|
||||
delaySlot = false;
|
||||
|
||||
oldPC = pc & 0xFFC;
|
||||
pc = nextPC & 0xFFC;
|
||||
nextPC += 4;
|
||||
|
||||
Instruction instr = line->code[i];
|
||||
Exec(instr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return CacheBlock(addr);
|
||||
}
|
||||
} // namespace n64
|
||||
|
||||
+332
-331
@@ -5,110 +5,111 @@
|
||||
#include <core/RDP.hpp>
|
||||
#include <core/mmio/MI.hpp>
|
||||
#include <Instruction.hpp>
|
||||
#include <JITUtils.hpp>
|
||||
|
||||
#define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF])
|
||||
#define GET_RSP_HALF(addr) ((RSP_BYTE(addr) << 8) | RSP_BYTE((addr) + 1))
|
||||
#define SET_RSP_HALF(addr, value) \
|
||||
do { \
|
||||
RSP_BYTE(addr) = ((value) >> 8) & 0xFF; \
|
||||
RSP_BYTE((addr) + 1) = (value) & 0xFF; \
|
||||
} \
|
||||
while (0)
|
||||
do { \
|
||||
RSP_BYTE(addr) = ((value) >> 8) & 0xFF; \
|
||||
RSP_BYTE((addr) + 1) = (value) & 0xFF; \
|
||||
} \
|
||||
while (0)
|
||||
#define GET_RSP_WORD(addr) ((GET_RSP_HALF(addr) << 16) | GET_RSP_HALF((addr) + 2))
|
||||
#define SET_RSP_WORD(addr, value) \
|
||||
do { \
|
||||
SET_RSP_HALF(addr, ((value) >> 16) & 0xFFFF); \
|
||||
SET_RSP_HALF((addr) + 2, (value) & 0xFFFF); \
|
||||
} \
|
||||
while (0)
|
||||
do { \
|
||||
SET_RSP_HALF(addr, ((value) >> 16) & 0xFFFF); \
|
||||
SET_RSP_HALF((addr) + 2, (value) & 0xFFFF); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
namespace n64 {
|
||||
union SPStatus {
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned halt : 1;
|
||||
unsigned broke : 1;
|
||||
unsigned dmaBusy : 1;
|
||||
unsigned dmaFull : 1;
|
||||
unsigned ioFull : 1;
|
||||
unsigned singleStep : 1;
|
||||
unsigned interruptOnBreak : 1;
|
||||
unsigned signal0 : 1;
|
||||
unsigned signal1 : 1;
|
||||
unsigned signal2 : 1;
|
||||
unsigned signal3 : 1;
|
||||
unsigned signal4 : 1;
|
||||
unsigned signal5 : 1;
|
||||
unsigned signal6 : 1;
|
||||
unsigned signal7 : 1;
|
||||
unsigned : 17;
|
||||
};
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned halt : 1;
|
||||
unsigned broke : 1;
|
||||
unsigned dmaBusy : 1;
|
||||
unsigned dmaFull : 1;
|
||||
unsigned ioFull : 1;
|
||||
unsigned singleStep : 1;
|
||||
unsigned interruptOnBreak : 1;
|
||||
unsigned signal0 : 1;
|
||||
unsigned signal1 : 1;
|
||||
unsigned signal2 : 1;
|
||||
unsigned signal3 : 1;
|
||||
unsigned signal4 : 1;
|
||||
unsigned signal5 : 1;
|
||||
unsigned signal6 : 1;
|
||||
unsigned signal7 : 1;
|
||||
unsigned : 17;
|
||||
};
|
||||
};
|
||||
|
||||
union SPStatusWrite {
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned clearHalt : 1;
|
||||
unsigned setHalt : 1;
|
||||
unsigned clearBroke : 1;
|
||||
unsigned clearIntr : 1;
|
||||
unsigned setIntr : 1;
|
||||
unsigned clearSstep : 1;
|
||||
unsigned setSstep : 1;
|
||||
unsigned clearIntrOnBreak : 1;
|
||||
unsigned setIntrOnBreak : 1;
|
||||
unsigned clearSignal0 : 1;
|
||||
unsigned setSignal0 : 1;
|
||||
unsigned clearSignal1 : 1;
|
||||
unsigned setSignal1 : 1;
|
||||
unsigned clearSignal2 : 1;
|
||||
unsigned setSignal2 : 1;
|
||||
unsigned clearSignal3 : 1;
|
||||
unsigned setSignal3 : 1;
|
||||
unsigned clearSignal4 : 1;
|
||||
unsigned setSignal4 : 1;
|
||||
unsigned clearSignal5 : 1;
|
||||
unsigned setSignal5 : 1;
|
||||
unsigned clearSignal6 : 1;
|
||||
unsigned setSignal6 : 1;
|
||||
unsigned clearSignal7 : 1;
|
||||
unsigned setSignal7 : 1;
|
||||
unsigned : 7;
|
||||
};
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned clearHalt : 1;
|
||||
unsigned setHalt : 1;
|
||||
unsigned clearBroke : 1;
|
||||
unsigned clearIntr : 1;
|
||||
unsigned setIntr : 1;
|
||||
unsigned clearSstep : 1;
|
||||
unsigned setSstep : 1;
|
||||
unsigned clearIntrOnBreak : 1;
|
||||
unsigned setIntrOnBreak : 1;
|
||||
unsigned clearSignal0 : 1;
|
||||
unsigned setSignal0 : 1;
|
||||
unsigned clearSignal1 : 1;
|
||||
unsigned setSignal1 : 1;
|
||||
unsigned clearSignal2 : 1;
|
||||
unsigned setSignal2 : 1;
|
||||
unsigned clearSignal3 : 1;
|
||||
unsigned setSignal3 : 1;
|
||||
unsigned clearSignal4 : 1;
|
||||
unsigned setSignal4 : 1;
|
||||
unsigned clearSignal5 : 1;
|
||||
unsigned setSignal5 : 1;
|
||||
unsigned clearSignal6 : 1;
|
||||
unsigned setSignal6 : 1;
|
||||
unsigned clearSignal7 : 1;
|
||||
unsigned setSignal7 : 1;
|
||||
unsigned : 7;
|
||||
};
|
||||
};
|
||||
|
||||
union SPDMALen {
|
||||
struct {
|
||||
unsigned len : 12;
|
||||
unsigned count : 8;
|
||||
unsigned skip : 12;
|
||||
};
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned len : 12;
|
||||
unsigned count : 8;
|
||||
unsigned skip : 12;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
union SPDMASPAddr {
|
||||
struct {
|
||||
unsigned address : 12;
|
||||
unsigned bank : 1;
|
||||
unsigned : 19;
|
||||
};
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned address : 12;
|
||||
unsigned bank : 1;
|
||||
unsigned : 19;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
union SPDMADRAMAddr {
|
||||
struct {
|
||||
unsigned address : 24;
|
||||
unsigned : 8;
|
||||
};
|
||||
u32 raw;
|
||||
struct {
|
||||
unsigned address : 24;
|
||||
unsigned : 8;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
union VPR {
|
||||
s16 selement[8];
|
||||
u16 element[8];
|
||||
u8 byte[16];
|
||||
u32 word[4];
|
||||
m128i single;
|
||||
s16 selement[8];
|
||||
u16 element[8];
|
||||
u8 byte[16];
|
||||
u32 word[4];
|
||||
m128i single;
|
||||
} __attribute__((packed));
|
||||
|
||||
static_assert(sizeof(VPR) == 16);
|
||||
@@ -119,277 +120,277 @@ struct Registers;
|
||||
#define DE(x) (((x) >> 11) & 0x1F)
|
||||
|
||||
struct RSP {
|
||||
bool divInLoaded = false;
|
||||
bool semaphore = false;
|
||||
std::array<u8, DMEM_SIZE> dmem{};
|
||||
std::array<u8, IMEM_SIZE> imem{};
|
||||
u16 oldPC{}, pc{}, nextPC{};
|
||||
s16 divIn{}, divOut{};
|
||||
u32 steps = 0;
|
||||
SPStatus spStatus{};
|
||||
SPDMASPAddr spDMASPAddr{};
|
||||
SPDMADRAMAddr spDMADRAMAddr{};
|
||||
SPDMASPAddr lastSuccessfulSPAddr{};
|
||||
SPDMADRAMAddr lastSuccessfulDRAMAddr{};
|
||||
SPDMALen spDMALen{};
|
||||
s32 gpr[32]{};
|
||||
VPR vpr[32]{};
|
||||
VPR vte{};
|
||||
VPR vce{};
|
||||
bool divInLoaded = false;
|
||||
bool semaphore = false;
|
||||
std::array<u8, DMEM_SIZE> dmem{};
|
||||
std::array<u8, IMEM_SIZE> imem{};
|
||||
u16 oldPC{}, pc{}, nextPC{};
|
||||
s16 divIn{}, divOut{};
|
||||
u32 steps = 0;
|
||||
SPStatus spStatus{};
|
||||
SPDMASPAddr spDMASPAddr{};
|
||||
SPDMADRAMAddr spDMADRAMAddr{};
|
||||
SPDMASPAddr lastSuccessfulSPAddr{};
|
||||
SPDMADRAMAddr lastSuccessfulDRAMAddr{};
|
||||
SPDMALen spDMALen{};
|
||||
s32 gpr[32]{};
|
||||
VPR vpr[32]{};
|
||||
VPR vte{};
|
||||
VPR vce{};
|
||||
|
||||
struct {
|
||||
VPR h{}, m{}, l{};
|
||||
} acc;
|
||||
struct {
|
||||
VPR h{}, m{}, l{};
|
||||
} acc;
|
||||
|
||||
struct {
|
||||
VPR l{}, h{};
|
||||
} vcc, vco;
|
||||
struct {
|
||||
VPR l{}, h{};
|
||||
} vcc, vco;
|
||||
|
||||
RSP();
|
||||
void Reset();
|
||||
CachedState<4, 0xFFF> cachedState;
|
||||
bool delaySlot = false, prevDelaySlot = false;
|
||||
|
||||
FORCE_INLINE void Step() {
|
||||
gpr[0] = 0;
|
||||
const u32 instr = ircolib::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
||||
oldPC = pc & 0xFFC;
|
||||
pc = nextPC & 0xFFC;
|
||||
nextPC += 4;
|
||||
RSP();
|
||||
void Reset();
|
||||
|
||||
Exec(instr);
|
||||
}
|
||||
void ExecuteCached();
|
||||
void CacheBlock(u16 addr);
|
||||
|
||||
void SetVTE(const VPR &vt, u8 e);
|
||||
auto Read(u32 addr) -> u32;
|
||||
void Write(u32 addr, u32 val);
|
||||
void Exec(Instruction instr);
|
||||
|
||||
FORCE_INLINE void SetPC(const u16 val) {
|
||||
oldPC = pc & 0xFFC;
|
||||
pc = val & 0xFFC;
|
||||
nextPC = pc + 4;
|
||||
}
|
||||
FORCE_INLINE void Step() {
|
||||
prevDelaySlot = delaySlot;
|
||||
delaySlot = false;
|
||||
gpr[0] = 0;
|
||||
const u32 instr = ircolib::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
||||
oldPC = pc & 0xFFC;
|
||||
pc = nextPC & 0xFFC;
|
||||
nextPC += 4;
|
||||
|
||||
[[nodiscard]] FORCE_INLINE s64 GetACC(const int e) const {
|
||||
s64 val = u64(acc.h.element[e]) << 32;
|
||||
val |= u64(acc.m.element[e]) << 16;
|
||||
val |= u64(acc.l.element[e]) << 00;
|
||||
if ((val & 0x0000800000000000) != 0) {
|
||||
val |= 0xFFFF000000000000;
|
||||
Exec(instr);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
FORCE_INLINE void SetACC(const int e, const s64 val) {
|
||||
acc.h.element[e] = val >> 32;
|
||||
acc.m.element[e] = val >> 16;
|
||||
acc.l.element[e] = val;
|
||||
}
|
||||
void SetVTE(const VPR &vt, u8 e);
|
||||
auto Read(u32 addr) -> u32;
|
||||
void Write(u32 addr, u32 val);
|
||||
void Exec(Instruction instr);
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u16 GetVCO() const {
|
||||
u16 value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const bool h = vco.h.element[7 - i] != 0;
|
||||
const bool l = vco.l.element[7 - i] != 0;
|
||||
const u32 mask = (l << i) | (h << (i + 8));
|
||||
value |= mask;
|
||||
FORCE_INLINE void SetPC(const u16 val) {
|
||||
oldPC = pc & 0xFFC;
|
||||
pc = val & 0xFFC;
|
||||
nextPC = pc + 4;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u16 GetVCC() const {
|
||||
u16 value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const bool h = vcc.h.element[7 - i] != 0;
|
||||
const bool l = vcc.l.element[7 - i] != 0;
|
||||
const u32 mask = (l << i) | (h << (i + 8));
|
||||
value |= mask;
|
||||
[[nodiscard]] FORCE_INLINE s64 GetACC(const int e) const {
|
||||
s64 val = u64(acc.h.element[e]) << 32;
|
||||
val |= u64(acc.m.element[e]) << 16;
|
||||
val |= u64(acc.l.element[e]) << 00;
|
||||
if ((val & 0x0000800000000000) != 0) {
|
||||
val |= 0xFFFF000000000000;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u8 GetVCE() const {
|
||||
u8 value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const bool l = vce.element[ELEMENT_INDEX(i)] != 0;
|
||||
value |= (l << i);
|
||||
FORCE_INLINE void SetACC(const int e, const s64 val) {
|
||||
acc.h.element[e] = val >> 32;
|
||||
acc.m.element[e] = val >> 16;
|
||||
acc.l.element[e] = val;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u32 ReadWord(u32 addr) const {
|
||||
addr &= 0xfff;
|
||||
return GET_RSP_WORD(addr);
|
||||
}
|
||||
|
||||
FORCE_INLINE void WriteWord(u32 addr, const u32 val) {
|
||||
addr &= 0xfff;
|
||||
SET_RSP_WORD(addr, val);
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u16 ReadHalf(u32 addr) const {
|
||||
addr &= 0xfff;
|
||||
return GET_RSP_HALF(addr);
|
||||
}
|
||||
|
||||
FORCE_INLINE void WriteHalf(u32 addr, const u16 val) {
|
||||
addr &= 0xfff;
|
||||
SET_RSP_HALF(addr, val);
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u8 ReadByte(u32 addr) const {
|
||||
addr &= 0xfff;
|
||||
return RSP_BYTE(addr);
|
||||
}
|
||||
|
||||
FORCE_INLINE void WriteByte(u32 addr, const u8 val) {
|
||||
addr &= 0xfff;
|
||||
RSP_BYTE(addr) = val;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool AcquireSemaphore() {
|
||||
if (semaphore) {
|
||||
return true;
|
||||
} else {
|
||||
semaphore = true;
|
||||
return false;
|
||||
[[nodiscard]] FORCE_INLINE u16 GetVCO() const {
|
||||
u16 value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const bool h = vco.h.element[7 - i] != 0;
|
||||
const bool l = vco.l.element[7 - i] != 0;
|
||||
const u32 mask = (l << i) | (h << (i + 8));
|
||||
value |= mask;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE void ReleaseSemaphore() { semaphore = false; }
|
||||
|
||||
void special(Instruction instr);
|
||||
void regimm(Instruction instr);
|
||||
void lwc2(Instruction instr);
|
||||
void swc2(Instruction instr);
|
||||
void cop2(Instruction instr);
|
||||
void cop0(Instruction instr);
|
||||
|
||||
void add(Instruction instr);
|
||||
void addi(Instruction instr);
|
||||
void and_(Instruction instr);
|
||||
void andi(Instruction instr);
|
||||
void b(Instruction instr, bool cond);
|
||||
void blink(Instruction instr, bool cond);
|
||||
void cfc2(Instruction instr);
|
||||
void ctc2(Instruction instr);
|
||||
void lb(Instruction instr);
|
||||
void lh(Instruction instr);
|
||||
void lw(Instruction instr);
|
||||
void lbu(Instruction instr);
|
||||
void lhu(Instruction instr);
|
||||
void lui(Instruction instr);
|
||||
void luv(Instruction instr);
|
||||
void lbv(Instruction instr);
|
||||
void ldv(Instruction instr);
|
||||
void lsv(Instruction instr);
|
||||
void llv(Instruction instr);
|
||||
void lrv(Instruction instr);
|
||||
void lqv(Instruction instr);
|
||||
void lfv(Instruction instr);
|
||||
void lhv(Instruction instr);
|
||||
void ltv(Instruction instr);
|
||||
void lpv(Instruction instr);
|
||||
void j(Instruction instr);
|
||||
void jal(Instruction instr);
|
||||
void jr(Instruction instr);
|
||||
void jalr(Instruction instr);
|
||||
void nor(Instruction instr);
|
||||
void or_(Instruction instr);
|
||||
void ori(Instruction instr);
|
||||
void xor_(Instruction instr);
|
||||
void xori(Instruction instr);
|
||||
void sb(Instruction instr);
|
||||
void sh(Instruction instr);
|
||||
void sw(Instruction instr);
|
||||
void swv(Instruction instr);
|
||||
void sub(Instruction instr);
|
||||
void sbv(Instruction instr);
|
||||
void sdv(Instruction instr);
|
||||
void stv(Instruction instr);
|
||||
void sqv(Instruction instr);
|
||||
void ssv(Instruction instr);
|
||||
void suv(Instruction instr);
|
||||
void slv(Instruction instr);
|
||||
void shv(Instruction instr);
|
||||
void sfv(Instruction instr);
|
||||
void srv(Instruction instr);
|
||||
void spv(Instruction instr);
|
||||
void sllv(Instruction instr);
|
||||
void srlv(Instruction instr);
|
||||
void srav(Instruction instr);
|
||||
void sll(Instruction instr);
|
||||
void srl(Instruction instr);
|
||||
void sra(Instruction instr);
|
||||
void slt(Instruction instr);
|
||||
void sltu(Instruction instr);
|
||||
void slti(Instruction instr);
|
||||
void sltiu(Instruction instr);
|
||||
void vabs(Instruction instr);
|
||||
void vadd(Instruction instr);
|
||||
void vaddc(Instruction instr);
|
||||
void vand(Instruction instr);
|
||||
void vnand(Instruction instr);
|
||||
void vch(Instruction instr);
|
||||
void vcr(Instruction instr);
|
||||
void vcl(Instruction instr);
|
||||
void vmacf(Instruction instr);
|
||||
void vmacu(Instruction instr);
|
||||
void vmacq(Instruction instr);
|
||||
void vmadh(Instruction instr);
|
||||
void vmadl(Instruction instr);
|
||||
void vmadm(Instruction instr);
|
||||
void vmadn(Instruction instr);
|
||||
void vmov(Instruction instr);
|
||||
void vmulf(Instruction instr);
|
||||
void vmulu(Instruction instr);
|
||||
void vmulq(Instruction instr);
|
||||
void vmudl(Instruction instr);
|
||||
void vmudh(Instruction instr);
|
||||
void vmudm(Instruction instr);
|
||||
void vmudn(Instruction instr);
|
||||
void vmrg(Instruction instr);
|
||||
void vlt(Instruction instr);
|
||||
void veq(Instruction instr);
|
||||
void vne(Instruction instr);
|
||||
void vge(Instruction instr);
|
||||
void vrcp(Instruction instr);
|
||||
void vrsq(Instruction instr);
|
||||
void vrcpl(Instruction instr);
|
||||
void vrsql(Instruction instr);
|
||||
void vrndp(Instruction instr);
|
||||
void vrndn(Instruction instr);
|
||||
void vrcph(Instruction instr);
|
||||
void vsar(Instruction instr);
|
||||
void vsub(Instruction instr);
|
||||
void vsubc(Instruction instr);
|
||||
void vxor(Instruction instr);
|
||||
void vnxor(Instruction instr);
|
||||
void vor(Instruction instr);
|
||||
void vnor(Instruction instr);
|
||||
void vzero(Instruction instr);
|
||||
void mfc0(const RDP &rdp, Instruction instr);
|
||||
void mtc0(Instruction instr) const;
|
||||
void mfc2(Instruction instr);
|
||||
void mtc2(Instruction instr);
|
||||
|
||||
template <bool toRdram>
|
||||
void DMA();
|
||||
void WriteStatus(u32 value);
|
||||
|
||||
private:
|
||||
FORCE_INLINE void branch(const u16 address, const bool cond) {
|
||||
if (cond) {
|
||||
nextPC = address & 0xFFC;
|
||||
[[nodiscard]] FORCE_INLINE u16 GetVCC() const {
|
||||
u16 value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const bool h = vcc.h.element[7 - i] != 0;
|
||||
const bool l = vcc.l.element[7 - i] != 0;
|
||||
const u32 mask = (l << i) | (h << (i + 8));
|
||||
value |= mask;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE void branch_likely(const u16 address, const bool cond) {
|
||||
if (cond) {
|
||||
nextPC = address & 0xFFC;
|
||||
} else {
|
||||
pc = nextPC & 0xFFC;
|
||||
nextPC = pc + 4;
|
||||
[[nodiscard]] FORCE_INLINE u8 GetVCE() const {
|
||||
u8 value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const bool l = vce.element[ELEMENT_INDEX(i)] != 0;
|
||||
value |= (l << i);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u32 ReadWord(u32 addr) const {
|
||||
addr &= 0xfff;
|
||||
return GET_RSP_WORD(addr);
|
||||
}
|
||||
|
||||
FORCE_INLINE void WriteWord(u32 addr, const u32 val) {
|
||||
addr &= 0xfff;
|
||||
SET_RSP_WORD(addr, val);
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u16 ReadHalf(u32 addr) const {
|
||||
addr &= 0xfff;
|
||||
return GET_RSP_HALF(addr);
|
||||
}
|
||||
|
||||
FORCE_INLINE void WriteHalf(u32 addr, const u16 val) {
|
||||
addr &= 0xfff;
|
||||
SET_RSP_HALF(addr, val);
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCE_INLINE u8 ReadByte(u32 addr) const {
|
||||
addr &= 0xfff;
|
||||
return RSP_BYTE(addr);
|
||||
}
|
||||
|
||||
FORCE_INLINE void WriteByte(u32 addr, const u8 val) {
|
||||
addr &= 0xfff;
|
||||
RSP_BYTE(addr) = val;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool AcquireSemaphore() {
|
||||
if (semaphore) {
|
||||
return true;
|
||||
} else {
|
||||
semaphore = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE void ReleaseSemaphore() { semaphore = false; }
|
||||
|
||||
void special(Instruction instr);
|
||||
void regimm(Instruction instr);
|
||||
void lwc2(Instruction instr);
|
||||
void swc2(Instruction instr);
|
||||
void cop2(Instruction instr);
|
||||
void cop0(Instruction instr);
|
||||
|
||||
void add(Instruction instr);
|
||||
void addi(Instruction instr);
|
||||
void and_(Instruction instr);
|
||||
void andi(Instruction instr);
|
||||
void b(Instruction instr, bool cond);
|
||||
void blink(Instruction instr, bool cond);
|
||||
void cfc2(Instruction instr);
|
||||
void ctc2(Instruction instr);
|
||||
void lb(Instruction instr);
|
||||
void lh(Instruction instr);
|
||||
void lw(Instruction instr);
|
||||
void lbu(Instruction instr);
|
||||
void lhu(Instruction instr);
|
||||
void lui(Instruction instr);
|
||||
void luv(Instruction instr);
|
||||
void lbv(Instruction instr);
|
||||
void ldv(Instruction instr);
|
||||
void lsv(Instruction instr);
|
||||
void llv(Instruction instr);
|
||||
void lrv(Instruction instr);
|
||||
void lqv(Instruction instr);
|
||||
void lfv(Instruction instr);
|
||||
void lhv(Instruction instr);
|
||||
void ltv(Instruction instr);
|
||||
void lpv(Instruction instr);
|
||||
void j(Instruction instr);
|
||||
void jal(Instruction instr);
|
||||
void jr(Instruction instr);
|
||||
void jalr(Instruction instr);
|
||||
void nor(Instruction instr);
|
||||
void or_(Instruction instr);
|
||||
void ori(Instruction instr);
|
||||
void xor_(Instruction instr);
|
||||
void xori(Instruction instr);
|
||||
void sb(Instruction instr);
|
||||
void sh(Instruction instr);
|
||||
void sw(Instruction instr);
|
||||
void swv(Instruction instr);
|
||||
void sub(Instruction instr);
|
||||
void sbv(Instruction instr);
|
||||
void sdv(Instruction instr);
|
||||
void stv(Instruction instr);
|
||||
void sqv(Instruction instr);
|
||||
void ssv(Instruction instr);
|
||||
void suv(Instruction instr);
|
||||
void slv(Instruction instr);
|
||||
void shv(Instruction instr);
|
||||
void sfv(Instruction instr);
|
||||
void srv(Instruction instr);
|
||||
void spv(Instruction instr);
|
||||
void sllv(Instruction instr);
|
||||
void srlv(Instruction instr);
|
||||
void srav(Instruction instr);
|
||||
void sll(Instruction instr);
|
||||
void srl(Instruction instr);
|
||||
void sra(Instruction instr);
|
||||
void slt(Instruction instr);
|
||||
void sltu(Instruction instr);
|
||||
void slti(Instruction instr);
|
||||
void sltiu(Instruction instr);
|
||||
void vabs(Instruction instr);
|
||||
void vadd(Instruction instr);
|
||||
void vaddc(Instruction instr);
|
||||
void vand(Instruction instr);
|
||||
void vnand(Instruction instr);
|
||||
void vch(Instruction instr);
|
||||
void vcr(Instruction instr);
|
||||
void vcl(Instruction instr);
|
||||
void vmacf(Instruction instr);
|
||||
void vmacu(Instruction instr);
|
||||
void vmacq(Instruction instr);
|
||||
void vmadh(Instruction instr);
|
||||
void vmadl(Instruction instr);
|
||||
void vmadm(Instruction instr);
|
||||
void vmadn(Instruction instr);
|
||||
void vmov(Instruction instr);
|
||||
void vmulf(Instruction instr);
|
||||
void vmulu(Instruction instr);
|
||||
void vmulq(Instruction instr);
|
||||
void vmudl(Instruction instr);
|
||||
void vmudh(Instruction instr);
|
||||
void vmudm(Instruction instr);
|
||||
void vmudn(Instruction instr);
|
||||
void vmrg(Instruction instr);
|
||||
void vlt(Instruction instr);
|
||||
void veq(Instruction instr);
|
||||
void vne(Instruction instr);
|
||||
void vge(Instruction instr);
|
||||
void vrcp(Instruction instr);
|
||||
void vrsq(Instruction instr);
|
||||
void vrcpl(Instruction instr);
|
||||
void vrsql(Instruction instr);
|
||||
void vrndp(Instruction instr);
|
||||
void vrndn(Instruction instr);
|
||||
void vrcph(Instruction instr);
|
||||
void vsar(Instruction instr);
|
||||
void vsub(Instruction instr);
|
||||
void vsubc(Instruction instr);
|
||||
void vxor(Instruction instr);
|
||||
void vnxor(Instruction instr);
|
||||
void vor(Instruction instr);
|
||||
void vnor(Instruction instr);
|
||||
void vzero(Instruction instr);
|
||||
void mfc0(const RDP &rdp, Instruction instr);
|
||||
void mtc0(Instruction instr) const;
|
||||
void mfc2(Instruction instr);
|
||||
void mtc2(Instruction instr);
|
||||
|
||||
template <bool toRdram>
|
||||
void DMA();
|
||||
void WriteStatus(u32 value);
|
||||
|
||||
private:
|
||||
FORCE_INLINE void branch(const u16 address, const bool cond) {
|
||||
if (cond) {
|
||||
nextPC = address & 0xFFC;
|
||||
delaySlot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace n64
|
||||
|
||||
Reference in New Issue
Block a user