forgot to increment v_current. Fuck me, thanks @wheremyfoodat
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -9,4 +9,6 @@ roms/
|
|||||||
.cache/
|
.cache/
|
||||||
.vscode/
|
.vscode/
|
||||||
vgcore.*
|
vgcore.*
|
||||||
*.data
|
*.data
|
||||||
|
disasm.txt
|
||||||
|
log.txt
|
||||||
@@ -13,6 +13,15 @@ find_package(fmt REQUIRED)
|
|||||||
|
|
||||||
add_executable(natsukashii main.cpp)
|
add_executable(natsukashii main.cpp)
|
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(OPTIMIZATIONS -g
|
||||||
|
#-fsanitize=address -fsanitize=undefined
|
||||||
|
)
|
||||||
|
#target_link_libraries(natsukashii PUBLIC -fsanitize=address -fsanitize=undefined)
|
||||||
|
elseif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
set(OPTIMIZATIONS -O3)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(natsukashii PUBLIC frontend n64 fmt)
|
target_link_libraries(natsukashii PUBLIC frontend n64 fmt)
|
||||||
target_include_directories(natsukashii PUBLIC . ../external)
|
target_include_directories(natsukashii PUBLIC . ../external)
|
||||||
target_compile_options(natsukashii PUBLIC -Wpedantic -Wimplicit-fallthrough -Wextra -Wall)
|
target_compile_options(natsukashii PUBLIC ${OPTIMIZATIONS} -Wpedantic -Wimplicit-fallthrough -Wextra -Wall)
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ void Core::Run(Window& window) {
|
|||||||
int frameCycles = 0;
|
int frameCycles = 0;
|
||||||
if(!pause && romLoaded) {
|
if(!pause && romLoaded) {
|
||||||
for (int i = 0; i < mmio.vi.numHalflines; i++) {
|
for (int i = 0; i < mmio.vi.numHalflines; i++) {
|
||||||
|
mmio.vi.current = (i << 1) + field;
|
||||||
|
|
||||||
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
|
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
|
||||||
InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI);
|
InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI);
|
||||||
}
|
}
|
||||||
@@ -54,7 +56,7 @@ void Core::Run(Window& window) {
|
|||||||
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
||||||
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
||||||
|
|
||||||
mmio.ai.Step(mem, cpu.regs, 1);
|
//mmio.ai.Step(mem, cpu.regs, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cycles -= mmio.vi.cyclesPerHalfline;
|
cycles -= mmio.vi.cyclesPerHalfline;
|
||||||
@@ -67,7 +69,7 @@ void Core::Run(Window& window) {
|
|||||||
UpdateScreenParallelRdp(*this, window, GetVI());
|
UpdateScreenParallelRdp(*this, window, GetVI());
|
||||||
|
|
||||||
int missedCycles = N64_CYCLES_PER_FRAME - frameCycles;
|
int missedCycles = N64_CYCLES_PER_FRAME - frameCycles;
|
||||||
mmio.ai.Step(mem, cpu.regs, missedCycles);
|
//mmio.ai.Step(mem, cpu.regs, missedCycles);
|
||||||
} else if(pause && romLoaded) {
|
} else if(pause && romLoaded) {
|
||||||
UpdateScreenParallelRdp(*this, window, GetVI());
|
UpdateScreenParallelRdp(*this, window, GetVI());
|
||||||
} else if(pause && !romLoaded) {
|
} else if(pause && !romLoaded) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
namespace natsukashii::core {
|
namespace n64 {
|
||||||
#define AUDIO_SAMPLE_RATE 48000
|
#define AUDIO_SAMPLE_RATE 48000
|
||||||
#define SYSTEM_SAMPLE_FORMAT AUDIO_F32SYS
|
#define SYSTEM_SAMPLE_FORMAT AUDIO_F32SYS
|
||||||
#define SYSTEM_SAMPLE_SIZE 4
|
#define SYSTEM_SAMPLE_SIZE 4
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
namespace natsukashii::core {
|
namespace n64 {
|
||||||
void PushSample(s16, s16);
|
void PushSample(s16, s16);
|
||||||
void InitAudio();
|
void InitAudio();
|
||||||
void AdjustSampleRate(int);
|
void AdjustSampleRate(int);
|
||||||
|
|||||||
@@ -41,17 +41,17 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
|
|||||||
bool old_exl = regs.cop0.status.exl;
|
bool old_exl = regs.cop0.status.exl;
|
||||||
|
|
||||||
if(!regs.cop0.status.exl) {
|
if(!regs.cop0.status.exl) {
|
||||||
if(regs.prevDelaySlot) { // TODO: cached value of delay_slot should be used, but Namco Museum breaks!
|
if(regs.delaySlot) { // TODO: cached value of delay_slot should be used, but Namco Museum breaks!
|
||||||
regs.cop0.cause.branchDelay = true;
|
regs.cop0.cause.branchDelay = true;
|
||||||
pc -= 4;
|
pc -= 4;
|
||||||
} else {
|
} else {
|
||||||
regs.cop0.cause.branchDelay = false;
|
regs.cop0.cause.branchDelay = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regs.cop0.status.exl = true;
|
||||||
regs.cop0.EPC = pc;
|
regs.cop0.EPC = pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
regs.cop0.status.exl = true;
|
|
||||||
regs.cop0.cause.copError = cop;
|
regs.cop0.cause.copError = cop;
|
||||||
regs.cop0.cause.exceptionCode = code;
|
regs.cop0.cause.exceptionCode = code;
|
||||||
|
|
||||||
@@ -59,12 +59,8 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
|
|||||||
util::panic("BEV bit set!\n");
|
util::panic("BEV bit set!\n");
|
||||||
} else {
|
} else {
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case Interrupt: case TLBModification:
|
case Interrupt ... TLBModification:
|
||||||
case AddressErrorLoad: case AddressErrorStore:
|
case AddressErrorLoad ... Trap:
|
||||||
case InstructionBusError: case DataBusError:
|
|
||||||
case Syscall: case Breakpoint:
|
|
||||||
case ReservedInstruction: case CoprocessorUnusable:
|
|
||||||
case Overflow: case Trap:
|
|
||||||
case FloatingPointError: case Watch:
|
case FloatingPointError: case Watch:
|
||||||
regs.SetPC(s64(s32(0x80000180)));
|
regs.SetPC(s64(s32(0x80000180)));
|
||||||
break;
|
break;
|
||||||
@@ -91,14 +87,28 @@ inline void HandleInterrupt(Registers& regs) {
|
|||||||
void Cpu::Step(Mem& mem) {
|
void Cpu::Step(Mem& mem) {
|
||||||
regs.gpr[0] = 0;
|
regs.gpr[0] = 0;
|
||||||
|
|
||||||
|
CheckCompareInterrupt(mem.mmio.mi, regs);
|
||||||
|
HandleInterrupt(regs);
|
||||||
|
|
||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
regs.delaySlot = false;
|
regs.delaySlot = false;
|
||||||
|
|
||||||
CheckCompareInterrupt(mem.mmio.mi, regs);
|
|
||||||
|
|
||||||
u32 instruction = mem.Read<u32>(regs, regs.pc, regs.pc);
|
u32 instruction = mem.Read<u32>(regs, regs.pc, regs.pc);
|
||||||
|
|
||||||
HandleInterrupt(regs);
|
/*cs_insn* insn;
|
||||||
|
u8 code[4]{};
|
||||||
|
memcpy(code, &instruction, 4);
|
||||||
|
|
||||||
|
u32 pc = regs.pc;
|
||||||
|
|
||||||
|
size_t count = cs_disasm(handle, code, 4, (u64)pc, 0, &insn);
|
||||||
|
if(count > 0) {
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
fprintf(log, "%s", fmt::format("0x{:016X}\t{}\t{}\n", insn[i].address, insn[i].mnemonic, insn[i].op_str).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
cs_free(insn, count);
|
||||||
|
}*/
|
||||||
|
|
||||||
regs.oldPC = regs.pc;
|
regs.oldPC = regs.pc;
|
||||||
regs.pc = regs.nextPC;
|
regs.pc = regs.nextPC;
|
||||||
|
|||||||
@@ -6,12 +6,24 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Cpu {
|
struct Cpu {
|
||||||
Cpu() { Reset(); }
|
Cpu() {
|
||||||
~Cpu() = default;
|
log = fopen("disasm.txt", "w");
|
||||||
|
if(cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle) != CS_ERR_OK) {
|
||||||
|
util::panic("Could not initialize capstone!\n");
|
||||||
|
}
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Cpu() {
|
||||||
|
fclose(log);
|
||||||
|
cs_close(&handle);
|
||||||
|
}
|
||||||
void Reset();
|
void Reset();
|
||||||
void Step(Mem&);
|
void Step(Mem&);
|
||||||
Registers regs;
|
Registers regs;
|
||||||
private:
|
private:
|
||||||
|
csh handle;
|
||||||
|
FILE* log;
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
|
|
||||||
void special(Mem&, u32);
|
void special(Mem&, u32);
|
||||||
|
|||||||
@@ -31,13 +31,12 @@ void RSP::Reset() {
|
|||||||
|
|
||||||
void RSP::Step(MI& mi, Registers& regs, RDP& rdp) {
|
void RSP::Step(MI& mi, Registers& regs, RDP& rdp) {
|
||||||
if(!spStatus.halt) {
|
if(!spStatus.halt) {
|
||||||
util::panic("RSP!\n");
|
gpr[0] = 0;
|
||||||
//gpr[0] = 0;
|
u32 instr = util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
||||||
//u32 instr = util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
oldPC = pc & 0xFFF;
|
||||||
//oldPC = pc & 0xFFF;
|
pc = nextPC & 0xFFF;
|
||||||
//pc = nextPC & 0xFFF;
|
nextPC += 4;
|
||||||
//nextPC += 4;
|
Exec(mi, regs, rdp, instr);
|
||||||
//Exec(mi, regs, rdp, instr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ void Cpu::branch_likely(bool cond, s64 address) {
|
|||||||
if (cond) {
|
if (cond) {
|
||||||
regs.nextPC = address;
|
regs.nextPC = address;
|
||||||
} else {
|
} else {
|
||||||
regs.SetPC(regs.pc + 4);
|
regs.SetPC(regs.nextPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,7 +580,7 @@ void Cpu::dsra32(u32 instr) {
|
|||||||
void Cpu::jr(u32 instr) {
|
void Cpu::jr(u32 instr) {
|
||||||
s32 address = regs.gpr[RS(instr)];
|
s32 address = regs.gpr[RS(instr)];
|
||||||
if ((address & 3) != 0) {
|
if ((address & 3) != 0) {
|
||||||
HandleTLBException(regs, (s64)((s32)address));
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ Cop0::Cop0() {
|
|||||||
void Cop0::Reset() {
|
void Cop0::Reset() {
|
||||||
cause.raw = 0xB000007C;
|
cause.raw = 0xB000007C;
|
||||||
status.raw = 0x241000E0;
|
status.raw = 0x241000E0;
|
||||||
PRId = 0x00000B22;
|
wired = 64;
|
||||||
|
index = 64;
|
||||||
|
PRId = 0x00000B00;
|
||||||
Config = 0x7006E463;
|
Config = 0x7006E463;
|
||||||
EPC = 0xFFFFFFFFFFFFFFFF;
|
EPC = 0xFFFFFFFFFFFFFFFF;
|
||||||
ErrorEPC = 0xFFFFFFFFFFFFFFFF;
|
ErrorEPC = 0xFFFFFFFFFFFFFFFF;
|
||||||
@@ -54,17 +56,17 @@ u32 Cop0::GetReg32(u8 addr) {
|
|||||||
|
|
||||||
u64 Cop0::GetReg64(u8 addr) {
|
u64 Cop0::GetReg64(u8 addr) {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 2: return entryLo0.raw;
|
case COP0_REG_ENTRYLO0: return entryLo0.raw;
|
||||||
case 3: return entryLo1.raw;
|
case COP0_REG_ENTRYLO1: return entryLo1.raw;
|
||||||
case 4: return context.raw;
|
case COP0_REG_CONTEXT: return context.raw;
|
||||||
case 8: return badVaddr;
|
case COP0_REG_BADVADDR: return badVaddr;
|
||||||
case 10: return entryHi.raw;
|
case COP0_REG_ENTRYHI: return entryHi.raw;
|
||||||
case 12: return status.raw;
|
case COP0_REG_STATUS: return status.raw;
|
||||||
case 14: return EPC;
|
case COP0_REG_EPC: return EPC;
|
||||||
case 15: return PRId;
|
case COP0_REG_PRID: return PRId;
|
||||||
case 17: return LLAddr;
|
case COP0_REG_LLADDR: return LLAddr;
|
||||||
case 20: return xcontext.raw & 0xFFFFFFFFFFFFFFF0;
|
case COP0_REG_XCONTEXT: return xcontext.raw & 0xFFFFFFFFFFFFFFF0;
|
||||||
case 30: return ErrorEPC;
|
case COP0_REG_ERROREPC: return ErrorEPC;
|
||||||
default:
|
default:
|
||||||
util::panic("Unsupported word read from COP0 register {}\n", index);
|
util::panic("Unsupported word read from COP0 register {}\n", index);
|
||||||
}
|
}
|
||||||
@@ -104,7 +106,9 @@ void Cop0::SetReg32(u8 addr, u32 value) {
|
|||||||
cause.ip0 = temp.ip0;
|
cause.ip0 = temp.ip0;
|
||||||
cause.ip1 = temp.ip1;
|
cause.ip1 = temp.ip1;
|
||||||
} break;
|
} break;
|
||||||
case COP0_REG_EPC: EPC = s64(s32(value)); break;
|
case COP0_REG_EPC:
|
||||||
|
EPC = s64(s32(value));
|
||||||
|
break;
|
||||||
case COP0_REG_PRID: break;
|
case COP0_REG_PRID: break;
|
||||||
case COP0_REG_CONFIG: {
|
case COP0_REG_CONFIG: {
|
||||||
Config &= ~CONFIG_MASK;
|
Config &= ~CONFIG_MASK;
|
||||||
@@ -121,8 +125,8 @@ void Cop0::SetReg32(u8 addr, u32 value) {
|
|||||||
case COP0_REG_TAGLO: TagLo = value; break;
|
case COP0_REG_TAGLO: TagLo = value; break;
|
||||||
case COP0_REG_TAGHI: TagHi = value; break;
|
case COP0_REG_TAGHI: TagHi = value; break;
|
||||||
case COP0_REG_ERROREPC: ErrorEPC = s64(s32(value)); break;
|
case COP0_REG_ERROREPC: ErrorEPC = s64(s32(value)); break;
|
||||||
case 7: case 21: case 22: break;
|
case 7: case 21: case 22:
|
||||||
case 23: case 24: case 25: break;
|
case 23: case 24: case 25:
|
||||||
case 31: break;
|
case 31: break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unsupported word read from COP0 register {}\n", index);
|
util::panic("Unsupported word read from COP0 register {}\n", index);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Cop1::Cop1() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::Reset() {
|
void Cop1::Reset() {
|
||||||
fcr0 = 0xa00;
|
fcr0 = 0;
|
||||||
fcr31.raw = 0;
|
fcr31.raw = 0;
|
||||||
memset(fgr, 0, 32 * sizeof(FGR));
|
memset(fgr, 0, 32 * sizeof(FGR));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ void AI::Reset() {
|
|||||||
dacRate = 0;
|
dacRate = 0;
|
||||||
bitrate = 0;
|
bitrate = 0;
|
||||||
dmaCount = 0;
|
dmaCount = 0;
|
||||||
memset(dmaLen, 0, 2);
|
|
||||||
memset(dmaAddr, 0, 2);
|
|
||||||
dmaAddrCarry = false;
|
dmaAddrCarry = false;
|
||||||
cycles = 0;
|
cycles = 0;
|
||||||
|
memset(dmaLen, 0, 2);
|
||||||
|
memset(dmaAddr, 0, 2);
|
||||||
dac = {44100, N64_CPU_FREQ / dac.freq, 16};
|
dac = {44100, N64_CPU_FREQ / dac.freq, 16};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +36,6 @@ auto AI::Read(u32 addr) const -> u32 {
|
|||||||
|
|
||||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
using namespace natsukashii::core;
|
|
||||||
|
|
||||||
void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x04500000:
|
case 0x04500000:
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ void InterruptRaise(MI &mi, Registers ®s, Interrupt intr) {
|
|||||||
|
|
||||||
UpdateInterrupt(mi, regs);
|
UpdateInterrupt(mi, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptLower(MI &mi, Registers ®s, Interrupt intr) {
|
void InterruptLower(MI &mi, Registers ®s, Interrupt intr) {
|
||||||
switch(intr) {
|
switch(intr) {
|
||||||
case Interrupt::VI:
|
case Interrupt::VI:
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
dramAddr = dram_addr + len;
|
dramAddr = dram_addr + len;
|
||||||
cartAddr = cart_addr + len;
|
cartAddr = cart_addr + len;
|
||||||
InterruptRaise(mi, regs, Interrupt::PI);
|
InterruptRaise(mi, regs, Interrupt::PI);
|
||||||
status = status & 0xFFFFFFFE;
|
status &= 0xFFFFFFFE;
|
||||||
util::logdebug("PI DMA from rdram to cart (size: {:.2f} MiB)\n", (float)len / 1048576);
|
util::logdebug("PI DMA from rdram to cart (size: {:.2f} MiB)\n", (float)len / 1048576);
|
||||||
} break;
|
} break;
|
||||||
case 0x0460000C: {
|
case 0x0460000C: {
|
||||||
@@ -75,7 +75,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
dramAddr = dram_addr + len;
|
dramAddr = dram_addr + len;
|
||||||
cartAddr = cart_addr + len;
|
cartAddr = cart_addr + len;
|
||||||
InterruptRaise(mi, regs, Interrupt::PI);
|
InterruptRaise(mi, regs, Interrupt::PI);
|
||||||
status = status & 0xFFFFFFFE;
|
status &= 0xFFFFFFFE;
|
||||||
util::logdebug("PI DMA from cart to rdram (size: {:.2f} MiB)\n", (float)len / 1048576);
|
util::logdebug("PI DMA from cart to rdram (size: {:.2f} MiB)\n", (float)len / 1048576);
|
||||||
} break;
|
} break;
|
||||||
case 0x04600010:
|
case 0x04600010:
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ VI::VI () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VI::Reset() {
|
void VI::Reset() {
|
||||||
|
status.raw = 0xF;
|
||||||
intr = 256;
|
intr = 256;
|
||||||
|
origin = 0;
|
||||||
|
width = 320;
|
||||||
|
current = 0;
|
||||||
|
vsync = 0;
|
||||||
|
hsync = 0;
|
||||||
numHalflines = 262;
|
numHalflines = 262;
|
||||||
numFields = 1;
|
numFields = 1;
|
||||||
cyclesPerHalfline = 1000;
|
cyclesPerHalfline = 1000;
|
||||||
@@ -35,7 +41,6 @@ u32 VI::Read(u32 paddr) const {
|
|||||||
default:
|
default:
|
||||||
util::panic("Unimplemented VI[%08X] read\n", paddr);
|
util::panic("Unimplemented VI[%08X] read\n", paddr);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
|
void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
|
||||||
|
|||||||
@@ -81,15 +81,15 @@ void RSP::Exec(MI &mi, Registers ®s, RDP &rdp, u32 instr) {
|
|||||||
u8 mask = (instr >> 26) & 0x3F;
|
u8 mask = (instr >> 26) & 0x3F;
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
//case 0x00: special(*this, instr); break;
|
//case 0x00: special(*this, instr); break;
|
||||||
//case 0x01: regimm(*this, instr); break;
|
case 0x01: regimm(*this, instr); break;
|
||||||
//case 0x02: j(instr); break;
|
case 0x02: j(instr); break;
|
||||||
//case 0x03: jal(instr); break;
|
//case 0x03: jal(instr); break;
|
||||||
//case 0x04: b(instr, gpr[RT(instr)] == gpr[RS(instr)]); break;
|
//case 0x04: b(instr, gpr[RT(instr)] == gpr[RS(instr)]); break;
|
||||||
//case 0x05: b(instr, gpr[RT(instr)] != gpr[RS(instr)]); break;
|
//case 0x05: b(instr, gpr[RT(instr)] != gpr[RS(instr)]); break;
|
||||||
//case 0x07: b(instr, gpr[RS(instr)] > 0); break;
|
//case 0x07: b(instr, gpr[RS(instr)] > 0); break;
|
||||||
//case 0x08: case 0x09: addi(instr); break;
|
case 0x08: case 0x09: addi(instr); break;
|
||||||
//case 0x0C: andi(instr); break;
|
//case 0x0C: andi(instr); break;
|
||||||
//case 0x0D: ori(instr); break;
|
case 0x0D: ori(instr); break;
|
||||||
//case 0x0F: lui(instr); break;
|
//case 0x0F: lui(instr); break;
|
||||||
//case 0x10: cop0(mi, regs, *this, rdp, instr); break;
|
//case 0x10: cop0(mi, regs, *this, rdp, instr); break;
|
||||||
//case 0x12: cop2(*this, instr); break;
|
//case 0x12: cop2(*this, instr); break;
|
||||||
@@ -100,7 +100,7 @@ void RSP::Exec(MI &mi, Registers ®s, RDP &rdp, u32 instr) {
|
|||||||
//case 0x2B: sw(instr); break;
|
//case 0x2B: sw(instr); break;
|
||||||
//case 0x32: lwc2(*this, instr); break;
|
//case 0x32: lwc2(*this, instr); break;
|
||||||
//case 0x3A: swc2(*this, instr); break;
|
//case 0x3A: swc2(*this, instr); break;
|
||||||
default: util::panic("Unhandled RSP instruction {} {}\n", (mask >> 3) & 7, mask & 7);
|
default: util::panic("Unhandled RSP instruction ({:06b})\n", mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,10 @@ void RSP::add(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RSP::addi(u32 instr) {
|
void RSP::addi(u32 instr) {
|
||||||
|
s32 op1 = gpr[RS(instr)];
|
||||||
|
s16 op2 = instr;
|
||||||
|
s32 result = op1 + op2;
|
||||||
|
gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSP::and_(u32 instr) {
|
void RSP::and_(u32 instr) {
|
||||||
@@ -128,7 +131,8 @@ void RSP::lqv(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RSP::j(u32 instr) {
|
void RSP::j(u32 instr) {
|
||||||
|
u32 target = (instr & 0x3ffffff) << 2;
|
||||||
|
nextPC = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSP::jal(u32 instr) {
|
void RSP::jal(u32 instr) {
|
||||||
@@ -148,7 +152,8 @@ void RSP::or_(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RSP::ori(u32 instr) {
|
void RSP::ori(u32 instr) {
|
||||||
|
s16 imm = instr;
|
||||||
|
gpr[RT(instr)] = imm | gpr[RS(instr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSP::sb(u32 instr) {
|
void RSP::sb(u32 instr) {
|
||||||
|
|||||||
Reference in New Issue
Block a user