fix PI DMA not firing due to opy-paste error + disassembly
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,3 +9,4 @@ roms/
|
|||||||
.cache/
|
.cache/
|
||||||
.vscode/
|
.vscode/
|
||||||
vgcore.*
|
vgcore.*
|
||||||
|
*.txt
|
||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -7,3 +7,7 @@
|
|||||||
[submodule "external/imgui/imgui"]
|
[submodule "external/imgui/imgui"]
|
||||||
path = external/imgui/imgui
|
path = external/imgui/imgui
|
||||||
url = https://github.com/ocornut/imgui
|
url = https://github.com/ocornut/imgui
|
||||||
|
[submodule "external/capstone"]
|
||||||
|
path = external/capstone
|
||||||
|
url = https://github.com/capstone-engine/capstone
|
||||||
|
branch = next
|
||||||
|
|||||||
1
external/capstone
vendored
Submodule
1
external/capstone
vendored
Submodule
Submodule external/capstone added at 0d0e684358
1
external/parallel-rdp/CMakeLists.txt
vendored
1
external/parallel-rdp/CMakeLists.txt
vendored
@@ -66,6 +66,7 @@ target_include_directories(parallel-rdp PUBLIC
|
|||||||
../imgui
|
../imgui
|
||||||
../imgui/imgui
|
../imgui/imgui
|
||||||
../imgui/imgui/backends
|
../imgui/imgui/backends
|
||||||
|
../capstone/include
|
||||||
.
|
.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ using u128 = __uint128_t;
|
|||||||
using s128 = __int128_t;
|
using s128 = __int128_t;
|
||||||
using m128 = __m128i;
|
using m128 = __m128i;
|
||||||
|
|
||||||
#define UINT128_MAX ((u128)0xFFFF'FFFF'FFFF'FFFF << 64) | 0xFFFF'FFFF'FFFF'FFFF
|
#define UINT128_MAX (((u128)0xFFFF'FFFF'FFFF'FFFF << 64) | 0xFFFF'FFFF'FFFF'FFFF)
|
||||||
#define UINT128_MIN 0
|
#define UINT128_MIN 0
|
||||||
#define INT128_MAX ((u128)0x7FFF'FFFF'FFFF'FFFF << 64) | 0xFFFF'FFFF'FFFF'FFFF
|
#define INT128_MAX (((u128)0x7FFF'FFFF'FFFF'FFFF << 64) | 0xFFFF'FFFF'FFFF'FFFF)
|
||||||
#define INT128_MIN (-INT128_MAX - 1LL)
|
#define INT128_MIN (-(INT128_MAX) - 1LL)
|
||||||
#define KiB * 1024
|
#define KiB * 1024
|
||||||
#define MiB (KiB * 1024)
|
#define MiB ((KiB) * 1024)
|
||||||
#define GiB (MiB * 1024)
|
#define GiB ((MiB) * 1024)
|
||||||
#define N64_CPU_FREQ 93750000
|
#define N64_CPU_FREQ 93750000
|
||||||
#define N64_CYCLES_PER_FRAME (N64_CPU_FREQ / 60)
|
#define N64_CYCLES_PER_FRAME ((N64_CPU_FREQ) / 60)
|
||||||
@@ -26,13 +26,17 @@ void App::Run() {
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.PollInputs(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core.initialized)
|
if(core.romLoaded)
|
||||||
core.Run();
|
core.Run();
|
||||||
|
|
||||||
if(core.initialized) UpdateScreenParallelRdp(window, core.GetVI());
|
if(core.romLoaded)
|
||||||
else UpdateScreenParallelRdpNoGame(window);
|
UpdateScreenParallelRdp(window, core.GetVI());
|
||||||
|
else
|
||||||
|
UpdateScreenParallelRdpNoGame(window);
|
||||||
|
|
||||||
SDL_Delay(16);
|
SDL_Delay(16);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ target_include_directories(frontend PUBLIC
|
|||||||
.
|
.
|
||||||
..
|
..
|
||||||
../../external
|
../../external
|
||||||
|
../../external/capstone/include
|
||||||
../../external/parallel-rdp
|
../../external/parallel-rdp
|
||||||
../../external/parallel-rdp/parallel-rdp-standalone/vulkan
|
../../external/parallel-rdp/parallel-rdp-standalone/vulkan
|
||||||
../../external/parallel-rdp/parallel-rdp-standalone/util
|
../../external/parallel-rdp/parallel-rdp-standalone/util
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ target_include_directories(frontend-imgui PUBLIC
|
|||||||
../../n64/core/cpu
|
../../n64/core/cpu
|
||||||
../../n64/core/cpu/registers
|
../../n64/core/cpu/registers
|
||||||
../../../external
|
../../../external
|
||||||
|
../../../external/capstone/include
|
||||||
../../../external/parallel-rdp/parallel-rdp-standalone
|
../../../external/parallel-rdp/parallel-rdp-standalone
|
||||||
../../../external/parallel-rdp/parallel-rdp-standalone/vulkan
|
../../../external/parallel-rdp/parallel-rdp-standalone/vulkan
|
||||||
../../../external/parallel-rdp/parallel-rdp-standalone/util
|
../../../external/parallel-rdp/parallel-rdp-standalone/util
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Window::Window(const n64::Core& core) {
|
|||||||
InitSDL();
|
InitSDL();
|
||||||
InitParallelRDP(core.GetRDRAM(), window);
|
InitParallelRDP(core.GetRDRAM(), window);
|
||||||
//InitImgui();
|
//InitImgui();
|
||||||
|
NFD::Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool Window::gotClosed(SDL_Event event) {
|
[[nodiscard]] bool Window::gotClosed(SDL_Event event) {
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ target_include_directories(n64 PUBLIC
|
|||||||
..
|
..
|
||||||
../../external
|
../../external
|
||||||
../../external/imgui/imgui
|
../../external/imgui/imgui
|
||||||
../../external/imgui/imgui/backends)
|
../../external/imgui/imgui/backends
|
||||||
|
../../external/capstone/include)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
#include <Core.hpp>
|
#include <Core.hpp>
|
||||||
#include <SDL2/SDL_events.h>
|
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
void Core::LoadROM(const std::string& rom) {
|
void Core::LoadROM(const std::string& rom) {
|
||||||
mem.LoadROM(rom);
|
mem.LoadROM(rom);
|
||||||
initialized = true;
|
romLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Run() {
|
void Core::Run() {
|
||||||
@@ -24,8 +23,7 @@ void Core::Run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::PollInputs(u32 windowID) {
|
void Core::PollInputs(SDL_Event e) {
|
||||||
SDL_Event event;
|
|
||||||
SDL_PollEvent(&event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
#include <Cpu.hpp>
|
#include <Cpu.hpp>
|
||||||
#include <Mem.hpp>
|
#include <Mem.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -9,10 +10,10 @@ struct Core {
|
|||||||
Core() = default;
|
Core() = default;
|
||||||
void LoadROM(const std::string&);
|
void LoadROM(const std::string&);
|
||||||
void Run();
|
void Run();
|
||||||
void PollInputs(u32);
|
void PollInputs(SDL_Event);
|
||||||
VI& GetVI() { return mem.mmio.vi; }
|
VI& GetVI() { return mem.mmio.vi; }
|
||||||
const u8* GetRDRAM() const { return mem.rdram.data(); }
|
const u8* GetRDRAM() const { return mem.rdram.data(); }
|
||||||
bool initialized = false;
|
bool romLoaded = false;
|
||||||
private:
|
private:
|
||||||
Mem mem;
|
Mem mem;
|
||||||
Cpu cpu;
|
Cpu cpu;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ project(core)
|
|||||||
add_subdirectory(cpu)
|
add_subdirectory(cpu)
|
||||||
|
|
||||||
add_subdirectory(../../../external/parallel-rdp temp)
|
add_subdirectory(../../../external/parallel-rdp temp)
|
||||||
|
add_subdirectory(../../../external/capstone temp1)
|
||||||
|
|
||||||
add_library(core
|
add_library(core
|
||||||
Cpu.hpp
|
Cpu.hpp
|
||||||
@@ -44,6 +45,7 @@ target_include_directories(core PUBLIC
|
|||||||
../../../external
|
../../../external
|
||||||
../../../external/imgui/imgui
|
../../../external/imgui/imgui
|
||||||
../../../external/imgui/imgui/backends
|
../../../external/imgui/imgui/backends
|
||||||
|
../../../external/capstone/include
|
||||||
mmio)
|
mmio)
|
||||||
|
|
||||||
target_link_libraries(core PUBLIC cpu parallel-rdp)
|
target_link_libraries(core PUBLIC cpu parallel-rdp capstone)
|
||||||
|
|||||||
@@ -4,6 +4,20 @@
|
|||||||
#include <util.hpp>
|
#include <util.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
|
Cpu::Cpu() {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle)) {
|
||||||
|
util::panic("Could not initialize capstone!\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Cpu::~Cpu() {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
cs_close(&handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
inline bool ShouldServiceInterrupt(Registers& regs) {
|
inline bool ShouldServiceInterrupt(Registers& regs) {
|
||||||
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;
|
||||||
@@ -49,22 +63,22 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
|
|||||||
|
|
||||||
regs.cop0.status.exl = true;
|
regs.cop0.status.exl = true;
|
||||||
regs.cop0.cause.copError = cop;
|
regs.cop0.cause.copError = cop;
|
||||||
regs.cop0.cause.exceptionCode = static_cast<u8>(code);
|
regs.cop0.cause.exceptionCode = code;
|
||||||
|
|
||||||
if(regs.cop0.status.bev) {
|
if(regs.cop0.status.bev) {
|
||||||
util::panic("BEV bit set!\n");
|
util::panic("BEV bit set!\n");
|
||||||
} else {
|
} else {
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case ExceptionCode::Interrupt: case ExceptionCode::TLBModification:
|
case Interrupt: case TLBModification:
|
||||||
case ExceptionCode::AddressErrorLoad: case ExceptionCode::AddressErrorStore:
|
case AddressErrorLoad: case AddressErrorStore:
|
||||||
case ExceptionCode::InstructionBusError: case ExceptionCode::DataBusError:
|
case InstructionBusError: case DataBusError:
|
||||||
case ExceptionCode::Syscall: case ExceptionCode::Breakpoint:
|
case Syscall: case Breakpoint:
|
||||||
case ExceptionCode::ReservedInstruction: case ExceptionCode::CoprocessorUnusable:
|
case ReservedInstruction: case CoprocessorUnusable:
|
||||||
case ExceptionCode::Overflow: case ExceptionCode::Trap:
|
case Overflow: case Trap:
|
||||||
case ExceptionCode::FloatingPointError: case ExceptionCode::Watch:
|
case FloatingPointError: case Watch:
|
||||||
regs.SetPC((s64)((s32)0x80000180));
|
regs.SetPC((s64)((s32)0x80000180));
|
||||||
break;
|
break;
|
||||||
case ExceptionCode::TLBLoad: case ExceptionCode::TLBStore:
|
case TLBLoad: case TLBStore:
|
||||||
if(old_exl || regs.cop0.tlbError == INVALID) {
|
if(old_exl || regs.cop0.tlbError == INVALID) {
|
||||||
regs.SetPC((s64)((s32)0x80000180));
|
regs.SetPC((s64)((s32)0x80000180));
|
||||||
} else if(Is64BitAddressing(regs.cop0, regs.cop0.badVaddr)) {
|
} else if(Is64BitAddressing(regs.cop0, regs.cop0.badVaddr)) {
|
||||||
@@ -73,7 +87,7 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
|
|||||||
regs.SetPC((s64)((s32)0x80000000));
|
regs.SetPC((s64)((s32)0x80000000));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unhandled exception! {}\n", static_cast<u8>(code));
|
default: util::panic("Unhandled exception! {}\n", code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,6 +98,24 @@ inline void HandleInterrupt(Registers& regs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cpu::LogInstruction(u32 instruction) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
u8 code[4]{};
|
||||||
|
u32 bswapped = be32toh(instruction);
|
||||||
|
memcpy(code, &instruction, 4);
|
||||||
|
count = cs_disasm(handle, code, 4, regs.pc, 0, &insn);
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
for(auto j = 0; j < count; j++) {
|
||||||
|
printf("%016lX:\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
|
||||||
|
}
|
||||||
|
cs_free(insn, count);
|
||||||
|
} else {
|
||||||
|
util::panic("Failed to disassemble {:08X}!", instruction);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::Step(Mem& mem) {
|
void Cpu::Step(Mem& mem) {
|
||||||
regs.gpr[0] = 0;
|
regs.gpr[0] = 0;
|
||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
@@ -92,6 +124,7 @@ void Cpu::Step(Mem& mem) {
|
|||||||
CheckCompareInterrupt(mem.mmio.mi, regs);
|
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);
|
||||||
|
LogInstruction(instruction);
|
||||||
|
|
||||||
HandleInterrupt(regs);
|
HandleInterrupt(regs);
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Registers.hpp>
|
#include <Registers.hpp>
|
||||||
#include <Mem.hpp>
|
#include <Mem.hpp>
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include <capstone/capstone.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Cpu {
|
struct Cpu {
|
||||||
Cpu() = default;
|
Cpu();
|
||||||
|
~Cpu();
|
||||||
void Step(Mem&);
|
void Step(Mem&);
|
||||||
Registers regs;
|
Registers regs;
|
||||||
private:
|
private:
|
||||||
|
#ifndef NDEBUG
|
||||||
|
csh handle{};
|
||||||
|
cs_insn *insn = nullptr;
|
||||||
|
size_t count{};
|
||||||
|
#endif
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
|
|
||||||
|
void LogInstruction(u32);
|
||||||
void special(Mem&, u32);
|
void special(Mem&, u32);
|
||||||
void regimm(u32);
|
void regimm(u32);
|
||||||
void Exec(Mem&, u32);
|
void Exec(Mem&, u32);
|
||||||
@@ -99,7 +110,7 @@ private:
|
|||||||
void xori(u32);
|
void xori(u32);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ExceptionCode : u8 {
|
enum ExceptionCode : u8 {
|
||||||
Interrupt,
|
Interrupt,
|
||||||
TLBModification,
|
TLBModification,
|
||||||
TLBLoad,
|
TLBLoad,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ void Mem::Write(Registers& regs, u32 vaddr, T val, s64 pc) {
|
|||||||
case 0x04000000 ... 0x04000FFF: util::WriteAccess<T>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); break;
|
case 0x04000000 ... 0x04000FFF: util::WriteAccess<T>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); break;
|
||||||
case 0x04001000 ... 0x04001FFF: util::WriteAccess<T>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); break;
|
case 0x04001000 ... 0x04001FFF: util::WriteAccess<T>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); break;
|
||||||
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Read(paddr); break;
|
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break;
|
||||||
case 0x10000000 ... 0x1FBFFFFF: util::WriteAccess<T>(cart.data(), paddr & romMask, val); break;
|
case 0x10000000 ... 0x1FBFFFFF: util::WriteAccess<T>(cart.data(), paddr & romMask, val); break;
|
||||||
case 0x1FC00000 ... 0x1FC007BF: util::WriteAccess<T>(pifBootrom, paddr & PIF_BOOTROM_DSIZE, val); break;
|
case 0x1FC00000 ... 0x1FC007BF: util::WriteAccess<T>(pifBootrom, paddr & PIF_BOOTROM_DSIZE, val); break;
|
||||||
case 0x1FC007C0 ... 0x1FC007FF: util::WriteAccess<T>(pifRam, paddr & PIF_RAM_DSIZE, val); break;
|
case 0x1FC007C0 ... 0x1FC007FF: util::WriteAccess<T>(pifRam, paddr & PIF_RAM_DSIZE, val); break;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ add_library(cpu
|
|||||||
target_include_directories(cpu PUBLIC registers
|
target_include_directories(cpu PUBLIC registers
|
||||||
. ..
|
. ..
|
||||||
../../../../external
|
../../../../external
|
||||||
|
../../../../external/capstone/include
|
||||||
../../../../src
|
../../../../src
|
||||||
../../
|
../../
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -175,28 +175,27 @@ void Cpu::lui(u32 instr) {
|
|||||||
|
|
||||||
void Cpu::lb(Mem& mem, u32 instr) {
|
void Cpu::lb(Mem& mem, u32 instr) {
|
||||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
regs.gpr[RT(instr)] = s64(mem.Read<s8>(regs, address, regs.oldPC));
|
regs.gpr[RT(instr)] = mem.Read<s8>(regs, address, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::lh(Mem& mem, u32 instr) {
|
void Cpu::lh(Mem& mem, u32 instr) {
|
||||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if ((address & 1) != 0) {
|
if ((address & 1) != 0) {
|
||||||
HandleTLBException(regs, (s64)((s32)address));
|
HandleTLBException(regs, s64(s32(address)));
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
regs.gpr[RT(instr)] = (s64)(s16)mem.Read<u16>(regs, address, regs.oldPC);
|
regs.gpr[RT(instr)] = mem.Read<s16>(regs, address, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::lw(Mem& mem, u32 instr) {
|
void Cpu::lw(Mem& mem, u32 instr) {
|
||||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if ((address & 3) != 0) {
|
if ((address & 3) != 0) {
|
||||||
HandleTLBException(regs, (s64)((s32)address));
|
HandleTLBException(regs, s64(s32(address)));
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 value = mem.Read<s32>(regs, address, regs.oldPC);
|
regs.gpr[RT(instr)] = mem.Read<s32>(regs, address, regs.oldPC);
|
||||||
regs.gpr[RT(instr)] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::ll(Mem& mem, u32 instr) {
|
void Cpu::ll(Mem& mem, u32 instr) {
|
||||||
@@ -209,8 +208,7 @@ void Cpu::ll(Mem& mem, u32 instr) {
|
|||||||
regs.LLBit = true;
|
regs.LLBit = true;
|
||||||
regs.cop0.LLAddr = address;
|
regs.cop0.LLAddr = address;
|
||||||
|
|
||||||
s32 value = mem.Read<s32>(regs, address, regs.oldPC);
|
regs.gpr[RT(instr)] = mem.Read<s32>(regs, address, regs.oldPC);
|
||||||
regs.gpr[RT(instr)] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::lwl(Mem& mem, u32 instr) {
|
void Cpu::lwl(Mem& mem, u32 instr) {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Registers;
|
struct Registers;
|
||||||
enum class ExceptionCode : u8;
|
enum ExceptionCode : u8;
|
||||||
|
|
||||||
TLBEntry* TLBTryMatch(Registers& regs, u32 vaddr, int* match);
|
TLBEntry* TLBTryMatch(Registers& regs, u32 vaddr, int* match);
|
||||||
bool ProbeTLB(Registers& regs, TLBAccessType access_type, u32 vaddr, u32& paddr, int* match);
|
bool ProbeTLB(Registers& regs, TLBAccessType access_type, u32 vaddr, u32& paddr, int* match);
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ auto PI::Read(MI& mi, u32 addr) const -> u32 {
|
|||||||
case 0x04600014: case 0x04600018: case 0x0460001C: case 0x04600020:
|
case 0x04600014: case 0x04600018: case 0x0460001C: case 0x04600020:
|
||||||
case 0x04600024: case 0x04600028: case 0x0460002C: case 0x04600030:
|
case 0x04600024: case 0x04600028: case 0x0460002C: case 0x04600030:
|
||||||
return stub[(addr & 0xff) - 5];
|
return stub[(addr & 0xff) - 5];
|
||||||
default: util::panic("Unhandled PI[{:08X}] read\n", addr); return 0;
|
default:
|
||||||
|
util::panic("Unhandled PI[{:08X}] read\n", addr); return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +69,8 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
case 0x04600024: case 0x04600028: case 0x0460002C: case 0x04600030:
|
case 0x04600024: case 0x04600028: case 0x0460002C: case 0x04600030:
|
||||||
stub[(addr & 0xff) - 5] = val & 0xff;
|
stub[(addr & 0xff) - 5] = val & 0xff;
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unhandled PI[{:08X}] write ({:08X})\n", val, addr);
|
default:
|
||||||
|
util::panic("Unhandled PI[{:08X}] write ({:08X})\n", val, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,20 @@ namespace n64 {
|
|||||||
inline void special(RSP& rsp, u32 instr) {
|
inline void special(RSP& rsp, u32 instr) {
|
||||||
u8 mask = instr & 0x3f;
|
u8 mask = instr & 0x3f;
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00: rsp.sll(instr); break;
|
//case 0x00: rsp.sll(instr); break;
|
||||||
case 0x04: rsp.sllv(instr); break;
|
//case 0x04: rsp.sllv(instr); break;
|
||||||
case 0x08: rsp.jr(instr); break;
|
//case 0x08: rsp.jr(instr); break;
|
||||||
case 0x0C:
|
//case 0x0C:
|
||||||
case 0x0D:
|
//case 0x0D:
|
||||||
rsp.spStatus.halt = true;
|
// rsp.spStatus.halt = true;
|
||||||
rsp.spStatus.broke = true;
|
// rsp.spStatus.broke = true;
|
||||||
break;
|
// break;
|
||||||
case 0x20: case 0x21:
|
//case 0x20: case 0x21:
|
||||||
rsp.add(instr);
|
// rsp.add(instr);
|
||||||
break;
|
// break;
|
||||||
case 0x24: rsp.and_(instr); break;
|
//case 0x24: rsp.and_(instr); break;
|
||||||
case 0x25: rsp.or_(instr); break;
|
//case 0x25: rsp.or_(instr); break;
|
||||||
case 0x27: rsp.nor(instr); break;
|
//case 0x27: rsp.nor(instr); break;
|
||||||
default: util::panic("Unhandled RSP special instruction %d %d\n", (mask >> 3) & 7, mask & 7);
|
default: util::panic("Unhandled RSP special instruction %d %d\n", (mask >> 3) & 7, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,8 +27,8 @@ inline void special(RSP& rsp, u32 instr) {
|
|||||||
inline void regimm(RSP& rsp, u32 instr) {
|
inline void regimm(RSP& rsp, u32 instr) {
|
||||||
u8 mask = ((instr >> 16) & 0x1F);
|
u8 mask = ((instr >> 16) & 0x1F);
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00: rsp.b(instr, (s32)rsp.gpr[RS(instr)] < 0); break;
|
//case 0x00: rsp.b(instr, (s32)rsp.gpr[RS(instr)] < 0); break;
|
||||||
case 0x01: rsp.b(instr, (s32)rsp.gpr[RS(instr)] >= 0); break;
|
//case 0x01: rsp.b(instr, (s32)rsp.gpr[RS(instr)] >= 0); break;
|
||||||
default: util::panic("Unhandled RSP regimm instruction %d %d\n", (mask >> 3) & 3, mask & 7);
|
default: util::panic("Unhandled RSP regimm instruction %d %d\n", (mask >> 3) & 3, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ inline void regimm(RSP& rsp, u32 instr) {
|
|||||||
inline void lwc2(RSP& rsp, u32 instr) {
|
inline void lwc2(RSP& rsp, u32 instr) {
|
||||||
u8 mask = (instr >> 11) & 0x1F;
|
u8 mask = (instr >> 11) & 0x1F;
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x04: rsp.lqv(instr); break;
|
//case 0x04: rsp.lqv(instr); break;
|
||||||
default: util::panic("Unhandled RSP LWC2 %d %d\n", (mask >> 3) & 3, mask & 7);
|
default: util::panic("Unhandled RSP LWC2 %d %d\n", (mask >> 3) & 3, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ inline void lwc2(RSP& rsp, u32 instr) {
|
|||||||
inline void swc2(RSP& rsp, u32 instr) {
|
inline void swc2(RSP& rsp, u32 instr) {
|
||||||
u8 mask = (instr >> 11) & 0x1F;
|
u8 mask = (instr >> 11) & 0x1F;
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x04: rsp.sqv(instr); break;
|
//case 0x04: rsp.sqv(instr); break;
|
||||||
default: util::panic("Unhandled RSP SWC2 %d %d\n", (mask >> 3) & 3, mask & 7);
|
default: util::panic("Unhandled RSP SWC2 %d %d\n", (mask >> 3) & 3, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,15 +55,15 @@ inline void cop2(RSP& rsp, u32 instr) {
|
|||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
switch(mask_sub) {
|
switch(mask_sub) {
|
||||||
case 0x02: rsp.cfc2(instr); break;
|
//case 0x02: rsp.cfc2(instr); break;
|
||||||
default: util::panic("Unhandled RSP COP2 sub %d %d\n", (mask_sub >> 3) & 3, mask_sub & 3);
|
default: util::panic("Unhandled RSP COP2 sub %d %d\n", (mask_sub >> 3) & 3, mask_sub & 3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x13: rsp.vabs(instr); break;
|
//case 0x13: rsp.vabs(instr); break;
|
||||||
case 0x1D: rsp.vsar(instr); break;
|
//case 0x1D: rsp.vsar(instr); break;
|
||||||
case 0x21: rsp.veq(instr); break;
|
//case 0x21: rsp.veq(instr); break;
|
||||||
case 0x22: rsp.vne(instr); break;
|
//case 0x22: rsp.vne(instr); break;
|
||||||
case 0x33: rsp.vmov(instr); break;
|
//case 0x33: rsp.vmov(instr); break;
|
||||||
default: util::panic("Unhandled RSP COP2 %d %d\n", (mask >> 3) & 7, mask & 7);
|
default: util::panic("Unhandled RSP COP2 %d %d\n", (mask >> 3) & 7, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,8 +71,8 @@ inline void cop2(RSP& rsp, u32 instr) {
|
|||||||
inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) {
|
inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) {
|
||||||
u8 mask = (instr >> 21) & 0x1F;
|
u8 mask = (instr >> 21) & 0x1F;
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00: rsp.mfc0(rdp, instr); break;
|
//case 0x00: rsp.mfc0(rdp, instr); break;
|
||||||
case 0x04: rsp.mtc0(mi, regs, rdp, instr); break;
|
//case 0x04: rsp.mtc0(mi, regs, rdp, instr); break;
|
||||||
default: util::panic("Unhandled RSP COP0 %d %d\n", (mask >> 3) & 3, mask & 7);
|
default: util::panic("Unhandled RSP COP0 %d %d\n", (mask >> 3) & 3, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,26 +80,26 @@ inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) {
|
|||||||
void RSP::Exec(MI &mi, Registers ®s, RDP &rdp, u32 instr) {
|
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;
|
||||||
case 0x21: lh(instr); break;
|
//case 0x21: lh(instr); break;
|
||||||
case 0x23: lw(instr); break;
|
//case 0x23: lw(instr); break;
|
||||||
case 0x28: sb(instr); break;
|
//case 0x28: sb(instr); break;
|
||||||
case 0x29: sh(instr); break;
|
//case 0x29: sh(instr); break;
|
||||||
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 %d %d\n", (mask >> 3) & 7, mask & 7);
|
default: util::panic("Unhandled RSP instruction %d %d\n", (mask >> 3) & 7, mask & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/util.hpp
11
src/util.hpp
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
enum MessageType : u8 {
|
enum MessageType : u8 {
|
||||||
Info, Warn, Error
|
Info, Warn, Error, Debug
|
||||||
};
|
};
|
||||||
|
|
||||||
template <MessageType messageType = Info, typename ...Args>
|
template <MessageType messageType = Info, typename ...Args>
|
||||||
@@ -18,7 +18,7 @@ constexpr void print(const std::string& fmt, Args... args) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
} else if constexpr(messageType == Warn) {
|
} else if constexpr(messageType == Warn) {
|
||||||
fmt::print(fg(fmt::color::yellow), fmt, args...);
|
fmt::print(fg(fmt::color::yellow), fmt, args...);
|
||||||
} else if constexpr(messageType == Info) {
|
} else if constexpr(messageType == Info || messageType == Debug) {
|
||||||
fmt::print(fmt, args...);
|
fmt::print(fmt, args...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,6 +38,13 @@ constexpr void info(const std::string& fmt, Args... args) {
|
|||||||
print(fmt, args...);
|
print(fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ...Args>
|
||||||
|
constexpr void logdebug(const std::string& fmt, Args... args) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
print(fmt, args...);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, bool HToBE = false>
|
template <typename T, bool HToBE = false>
|
||||||
auto GetSwapFunc(T num) -> T {
|
auto GetSwapFunc(T num) -> T {
|
||||||
static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "GetSwapFunc used with invalid size!");
|
static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "GetSwapFunc used with invalid size!");
|
||||||
|
|||||||
Reference in New Issue
Block a user