No more segfault in JIT. Keeps executing the same blocks over and over though...
This commit is contained in:
12
external/parallel-rdp/ParallelRDPWrapper.cpp
vendored
12
external/parallel-rdp/ParallelRDPWrapper.cpp
vendored
@@ -79,7 +79,7 @@ public:
|
|||||||
unsigned int num_extensions = 64;
|
unsigned int num_extensions = 64;
|
||||||
|
|
||||||
if (!SDL_Vulkan_GetInstanceExtensions(g_Window, &num_extensions, extensions)) {
|
if (!SDL_Vulkan_GetInstanceExtensions(g_Window, &num_extensions, extensions)) {
|
||||||
util::panic("SDL_Vulkan_GetInstanceExtensions failed: {}", SDL_GetError());
|
Util::panic("SDL_Vulkan_GetInstanceExtensions failed: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
auto vec = std::vector<const char*>();
|
auto vec = std::vector<const char*>();
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ public:
|
|||||||
VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice gpu) override {
|
VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice gpu) override {
|
||||||
VkSurfaceKHR vk_surface;
|
VkSurfaceKHR vk_surface;
|
||||||
if (!SDL_Vulkan_CreateSurface(g_Window, instance, &vk_surface)) {
|
if (!SDL_Vulkan_CreateSurface(g_Window, instance, &vk_surface)) {
|
||||||
util::panic("Failed to create Vulkan window surface: {}", SDL_GetError());
|
Util::panic("Failed to create Vulkan window surface: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
return vk_surface;
|
return vk_surface;
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ WSI* LoadWSIPlatform(Vulkan::WSIPlatform* wsi_platform, std::unique_ptr<Parallel
|
|||||||
wsi->set_present_mode(PresentMode::SyncToVBlank);
|
wsi->set_present_mode(PresentMode::SyncToVBlank);
|
||||||
Context::SystemHandles handles;
|
Context::SystemHandles handles;
|
||||||
if (!wsi->init_simple(1, handles)) {
|
if (!wsi->init_simple(1, handles)) {
|
||||||
util::panic("Failed to initialize WSI!");
|
Util::panic("Failed to initialize WSI!");
|
||||||
}
|
}
|
||||||
|
|
||||||
windowInfo = std::move(newWindowInfo);
|
windowInfo = std::move(newWindowInfo);
|
||||||
@@ -157,8 +157,8 @@ void LoadParallelRDP(const u8* rdram, SDL_Window* window) {
|
|||||||
fragLayout.sets[0].array_size[0] = 1;
|
fragLayout.sets[0].array_size[0] = 1;
|
||||||
|
|
||||||
u32* fullscreenQuadVert, *fullscreenQuadFrag;
|
u32* fullscreenQuadVert, *fullscreenQuadFrag;
|
||||||
auto sizeVert = util::ReadFileBinary("resources/vert.spv", &fullscreenQuadVert);
|
auto sizeVert = Util::ReadFileBinary("resources/vert.spv", &fullscreenQuadVert);
|
||||||
auto sizeFrag = util::ReadFileBinary("resources/frag.spv", &fullscreenQuadFrag);
|
auto sizeFrag = Util::ReadFileBinary("resources/frag.spv", &fullscreenQuadFrag);
|
||||||
|
|
||||||
fullscreen_quad_program = wsi->get_device().request_program(fullscreenQuadVert, sizeVert, fullscreenQuadFrag, sizeFrag, &vertLayout, &fragLayout);
|
fullscreen_quad_program = wsi->get_device().request_program(fullscreenQuadVert, sizeVert, fullscreenQuadFrag, sizeFrag, &vertLayout, &fragLayout);
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ void LoadParallelRDP(const u8* rdram, SDL_Window* window) {
|
|||||||
offset, 8 * 1024 * 1024, 4 * 1024 * 1024, flags);
|
offset, 8 * 1024 * 1024, 4 * 1024 * 1024, flags);
|
||||||
|
|
||||||
if (!command_processor->device_is_supported()) {
|
if (!command_processor->device_is_supported()) {
|
||||||
util::panic("This device probably does not support 8/16-bit storage. Make sure you're using up-to-date drivers!");
|
Util::panic("This device probably does not support 8/16-bit storage. Make sure you're using up-to-date drivers!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,17 +68,17 @@ endif()
|
|||||||
if(${CMAKE_BUILD_TYPE} MATCHES Release)
|
if(${CMAKE_BUILD_TYPE} MATCHES Release)
|
||||||
set_property(TARGET gadolinium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
set_property(TARGET gadolinium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_compile_options(/O2)
|
target_compile_options(gadolinium PRIVATE /O2)
|
||||||
else()
|
else()
|
||||||
add_compile_options(-O3)
|
target_compile_options(gadolinium PRIVATE -O3)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_compile_options(/Od)
|
target_compile_options(gadolinium PRIVATE /Od)
|
||||||
else()
|
else()
|
||||||
add_compile_options(-fsanitize=address)
|
target_compile_options(gadolinium PRIVATE -fsanitize=address)
|
||||||
add_link_options(-fsanitize=address)
|
target_link_options(gadolinium PRIVATE -fsanitize=address)
|
||||||
add_compile_options(-g)
|
target_compile_options(gadolinium PRIVATE -g)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
namespace util {
|
namespace Util {
|
||||||
enum State {
|
enum State {
|
||||||
Idling,
|
Idling,
|
||||||
Playing,
|
Playing,
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ struct Core {
|
|||||||
VI& GetVI() { return mem.mmio.vi; }
|
VI& GetVI() { return mem.mmio.vi; }
|
||||||
|
|
||||||
void CpuReset() {
|
void CpuReset() {
|
||||||
switch(cpuType) {
|
regs.Reset();
|
||||||
case CpuType::Dynarec: break;
|
|
||||||
case CpuType::Interpreter: break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CpuStep() {
|
int CpuStep() {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ void LoadTAS(const char* filename) {
|
|||||||
FILE *fp = fopen(filename, "rb");
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
util::panic("Error opening the movie file {}! Are you sure it's a valid movie and that it exists?", filename);
|
Util::panic("Error opening the movie file {}! Are you sure it's a valid movie and that it exists?", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
@@ -85,31 +85,31 @@ void LoadTAS(const char* filename) {
|
|||||||
loaded_tas_movie_size = size;
|
loaded_tas_movie_size = size;
|
||||||
|
|
||||||
if (!loaded_tas_movie) {
|
if (!loaded_tas_movie) {
|
||||||
util::panic("Error loading movie!");
|
Util::panic("Error loading movie!");
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&loaded_tas_movie_header, buf, sizeof(TASMovieHeader));
|
memcpy(&loaded_tas_movie_header, buf, sizeof(TASMovieHeader));
|
||||||
|
|
||||||
if (loaded_tas_movie_header.signature[0] != 0x4D || loaded_tas_movie_header.signature[1] != 0x36 || loaded_tas_movie_header.signature[2] != 0x34 || loaded_tas_movie_header.signature[3] != 0x1A) {
|
if (loaded_tas_movie_header.signature[0] != 0x4D || loaded_tas_movie_header.signature[1] != 0x36 || loaded_tas_movie_header.signature[2] != 0x34 || loaded_tas_movie_header.signature[3] != 0x1A) {
|
||||||
util::panic("Failed to load movie: incorrect signature. Are you sure this is a valid movie?");
|
Util::panic("Failed to load movie: incorrect signature. Are you sure this is a valid movie?");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loaded_tas_movie_header.version != 3) {
|
if (loaded_tas_movie_header.version != 3) {
|
||||||
util::panic("This movie is version {}: only version 3 is supported.", loaded_tas_movie_header.version);
|
Util::panic("This movie is version {}: only version 3 is supported.", loaded_tas_movie_header.version);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loaded_tas_movie_header.startType != 2) {
|
if (loaded_tas_movie_header.startType != 2) {
|
||||||
util::panic("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)", loaded_tas_movie_header.startType);
|
Util::panic("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)", loaded_tas_movie_header.startType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check ROM CRC32 here
|
// TODO: check ROM CRC32 here
|
||||||
|
|
||||||
util::print("Loaded movie '{}' ", loaded_tas_movie_header.movie_description);
|
Util::print("Loaded movie '{}' ", loaded_tas_movie_header.movie_description);
|
||||||
util::print("by {}\n", loaded_tas_movie_header.author_name);
|
Util::print("by {}\n", loaded_tas_movie_header.author_name);
|
||||||
util::print("{} controller(s) connected\n", loaded_tas_movie_header.numControllers);
|
Util::print("{} controller(s) connected\n", loaded_tas_movie_header.numControllers);
|
||||||
|
|
||||||
if (loaded_tas_movie_header.numControllers != 1) {
|
if (loaded_tas_movie_header.numControllers != 1) {
|
||||||
util::panic("Currently, only movies with 1 controller connected are supported.\n");
|
Util::panic("Currently, only movies with 1 controller connected are supported.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded_tas_movie_index = sizeof(TASMovieHeader) - 4; // skip header
|
loaded_tas_movie_index = sizeof(TASMovieHeader) - 4; // skip header
|
||||||
@@ -120,22 +120,22 @@ bool tas_movie_loaded() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void LogController(const n64::Controller& controller) {
|
inline void LogController(const n64::Controller& controller) {
|
||||||
util::print("c_right: {}\n", controller.c_right);
|
Util::print("c_right: {}\n", controller.c_right);
|
||||||
util::print("c_left: {}\n", controller.c_left);
|
Util::print("c_left: {}\n", controller.c_left);
|
||||||
util::print("c_down: {}\n", controller.c_down);
|
Util::print("c_down: {}\n", controller.c_down);
|
||||||
util::print("c_up: {}\n", controller.c_up);
|
Util::print("c_up: {}\n", controller.c_up);
|
||||||
util::print("r: {}\n", controller.r);
|
Util::print("r: {}\n", controller.r);
|
||||||
util::print("l: {}\n", controller.l);
|
Util::print("l: {}\n", controller.l);
|
||||||
util::print("dp_right: {}\n", controller.dp_right);
|
Util::print("dp_right: {}\n", controller.dp_right);
|
||||||
util::print("dp_left: {}\n", controller.dp_left);
|
Util::print("dp_left: {}\n", controller.dp_left);
|
||||||
util::print("dp_down: {}\n", controller.dp_down);
|
Util::print("dp_down: {}\n", controller.dp_down);
|
||||||
util::print("dp_up: {}\n", controller.dp_up);
|
Util::print("dp_up: {}\n", controller.dp_up);
|
||||||
util::print("z: {}\n", controller.z);
|
Util::print("z: {}\n", controller.z);
|
||||||
util::print("b: {}\n", controller.b);
|
Util::print("b: {}\n", controller.b);
|
||||||
util::print("a: {}\n", controller.a);
|
Util::print("a: {}\n", controller.a);
|
||||||
util::print("start: {}\n", controller.start);
|
Util::print("start: {}\n", controller.start);
|
||||||
util::print("joy_x: {}\n", controller.joy_x);
|
Util::print("joy_x: {}\n", controller.joy_x);
|
||||||
util::print("joy_y: {}\n\n", controller.joy_y);
|
Util::print("joy_y: {}\n\n", controller.joy_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
n64::Controller tas_next_inputs() {
|
n64::Controller tas_next_inputs() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
#include <MemoryHelpers.hpp>
|
#include <MemoryHelpers.hpp>
|
||||||
|
|
||||||
namespace util {
|
namespace Util {
|
||||||
enum RomTypes {
|
enum RomTypes {
|
||||||
Z64 = 0x80371240,
|
Z64 = 0x80371240,
|
||||||
N64 = 0x40123780,
|
N64 = 0x40123780,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Scheduler scheduler;
|
|||||||
|
|
||||||
Scheduler::Scheduler() {
|
Scheduler::Scheduler() {
|
||||||
events.push({UINT64_MAX, [](n64::Mem&, n64::Registers&){
|
events.push({UINT64_MAX, [](n64::Mem&, n64::Registers&){
|
||||||
util::panic("How the fuck did we get here?!\n");
|
Util::panic("How the fuck did we get here?!\n");
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void InitAudio() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!audioDev) {
|
if(!audioDev) {
|
||||||
util::panic("Failed to initialize SDL Audio: {}", SDL_GetError());
|
Util::panic("Failed to initialize SDL Audio: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_PauseAudioDevice(audioDev, false);
|
SDL_PauseAudioDevice(audioDev, false);
|
||||||
@@ -61,7 +61,7 @@ void InitAudio() {
|
|||||||
audioStreamMutex = SDL_CreateMutex();
|
audioStreamMutex = SDL_CreateMutex();
|
||||||
|
|
||||||
if(!audioStreamMutex) {
|
if(!audioStreamMutex) {
|
||||||
util::panic("Unable to initialize audio mutex: {}", SDL_GetError());
|
Util::panic("Unable to initialize audio mutex: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,46 @@
|
|||||||
#include <Dynarec.hpp>
|
#include <Dynarec.hpp>
|
||||||
#include <Registers.hpp>
|
#include <Registers.hpp>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace n64::JIT {
|
namespace n64::JIT {
|
||||||
Dynarec::Dynarec() : code(Xbyak::DEFAULT_MAX_CODE_SIZE, Xbyak::AutoGrow) {}
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
Dynarec::~Dynarec() {
|
||||||
|
dumpCode.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dynarec::Dynarec() : code(DEFAULT_MAX_CODE_SIZE, AutoGrow) {
|
||||||
|
if(fs::exists("jit.dump")) {
|
||||||
|
fs::remove("jit.dump");
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpCode.open("jit.dump", std::ios::app | std::ios::binary);
|
||||||
|
code.setProtectMode(CodeGenerator::PROTECT_RWE);
|
||||||
|
}
|
||||||
|
|
||||||
void Dynarec::Recompile(Registers& regs, Mem& mem) {
|
void Dynarec::Recompile(Registers& regs, Mem& mem) {
|
||||||
bool branch = false, prevBranch = false;
|
bool branch = false, prevBranch = false;
|
||||||
u32 start_addr = regs.pc;
|
u32 start_addr = regs.pc;
|
||||||
Fn block = code.getCurr<Fn>();
|
Fn block = code.getCurr<Fn>();
|
||||||
|
|
||||||
|
code.sub(code.rsp, 8);
|
||||||
|
|
||||||
while(!prevBranch) {
|
while(!prevBranch) {
|
||||||
instrInBlock++;
|
instrInBlock++;
|
||||||
prevBranch = branch;
|
prevBranch = branch;
|
||||||
u32 instr = mem.Read32(regs, regs.pc, regs.pc);
|
u32 instr = mem.Read32(regs, start_addr, start_addr);
|
||||||
|
|
||||||
regs.oldPC = regs.pc;
|
start_addr += 4;
|
||||||
regs.pc = regs.nextPC;
|
|
||||||
regs.nextPC += 4;
|
|
||||||
|
|
||||||
|
code.mov(code.rdi, (u64)®s);
|
||||||
branch = Exec(regs, mem, instr);
|
branch = Exec(regs, mem, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code.add(code.rsp, 8);
|
||||||
code.ret();
|
code.ret();
|
||||||
codeCache[start_addr >> 20][start_addr & 0xFFF] = block;
|
dumpCode.write(code.getCode<char*>(), code.getSize());
|
||||||
|
u32 pc = regs.pc & 0xffffffff;
|
||||||
|
codeCache[pc >> 20][pc & 0xFFF] = block;
|
||||||
block();
|
block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <xbyak/xbyak.h>
|
#include <xbyak/xbyak.h>
|
||||||
#include <backend/core/Mem.hpp>
|
#include <backend/core/Mem.hpp>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
namespace n64::JIT {
|
namespace n64::JIT {
|
||||||
|
using namespace Xbyak;
|
||||||
|
using namespace Xbyak::util;
|
||||||
using Fn = void (*)();
|
using Fn = void (*)();
|
||||||
|
|
||||||
struct Dynarec {
|
struct Dynarec {
|
||||||
Dynarec();
|
Dynarec();
|
||||||
|
~Dynarec();
|
||||||
int Step(Mem&, n64::Registers&);
|
int Step(Mem&, n64::Registers&);
|
||||||
void Reset() {
|
void Reset() {
|
||||||
code.reset();
|
code.reset();
|
||||||
}
|
}
|
||||||
u64 cop2Latch{};
|
u64 cop2Latch{};
|
||||||
Xbyak::CodeGenerator code;
|
CodeGenerator code;
|
||||||
private:
|
private:
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
Fn* codeCache[0x80000]{};
|
Fn* codeCache[0x80000]{};
|
||||||
int instrInBlock = 0;
|
int instrInBlock = 0;
|
||||||
|
std::ofstream dumpCode;
|
||||||
|
|
||||||
void Recompile(n64::Registers&, Mem&);
|
void Recompile(n64::Registers&, Mem&);
|
||||||
void AllocateOuter(n64::Registers&);
|
void AllocateOuter(n64::Registers&);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ u32 MMIO::Read(u32 addr) {
|
|||||||
case 0x04700000 ... 0x047FFFFF: return ri.Read(addr);
|
case 0x04700000 ... 0x047FFFFF: return ri.Read(addr);
|
||||||
case 0x04800000 ... 0x048FFFFF: return si.Read(mi, addr);
|
case 0x04800000 ... 0x048FFFFF: return si.Read(mi, addr);
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled mmio read at addr {:08X}\n", addr);
|
Util::panic("Unhandled mmio read at addr {:08X}\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ void MMIO::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
case 0x04700000 ... 0x047FFFFF: ri.Write(addr, val); break;
|
case 0x04700000 ... 0x047FFFFF: ri.Write(addr, val); break;
|
||||||
case 0x04800000 ... 0x048FFFFF: si.Write(mem, regs, addr, val); break;
|
case 0x04800000 ... 0x048FFFFF: si.Write(mem, regs, addr, val); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled mmio write at addr {:08X} with val {:08X}\n", addr, val);
|
Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}\n", addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ CartInfo Mem::LoadROM(const std::string& filename) {
|
|||||||
file.unsetf(std::ios::skipws);
|
file.unsetf(std::ios::skipws);
|
||||||
|
|
||||||
if(!file.is_open()) {
|
if(!file.is_open()) {
|
||||||
util::panic("Unable to open {}!", filename);
|
Util::panic("Unable to open {}!", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
file.seekg(0, std::ios::end);
|
file.seekg(0, std::ios::end);
|
||||||
auto size = file.tellg();
|
auto size = file.tellg();
|
||||||
auto sizeAdjusted = util::NextPow2(size);
|
auto sizeAdjusted = Util::NextPow2(size);
|
||||||
romMask = sizeAdjusted - 1;
|
romMask = sizeAdjusted - 1;
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ CartInfo Mem::LoadROM(const std::string& filename) {
|
|||||||
CartInfo result{};
|
CartInfo result{};
|
||||||
|
|
||||||
u32 cicChecksum;
|
u32 cicChecksum;
|
||||||
util::SwapN64Rom(sizeAdjusted, cart.data(), result.crc, cicChecksum);
|
Util::SwapN64Rom(sizeAdjusted, cart.data(), result.crc, cicChecksum);
|
||||||
memcpy(mmio.rsp.dmem, cart.data(), 0x1000);
|
memcpy(mmio.rsp.dmem, cart.data(), 0x1000);
|
||||||
|
|
||||||
SetCICType(result.cicType, cicChecksum);
|
SetCICType(result.cicType, cicChecksum);
|
||||||
@@ -77,9 +77,9 @@ bool MapVAddr(Registers& regs, TLBAccessType accessType, u64 vaddr, u32& paddr)
|
|||||||
case 0 ... 3: case 7:
|
case 0 ... 3: case 7:
|
||||||
return ProbeTLB(regs, accessType, vaddr, paddr, nullptr);
|
return ProbeTLB(regs, accessType, vaddr, paddr, nullptr);
|
||||||
case 4 ... 5: return true;
|
case 4 ... 5: return true;
|
||||||
case 6: util::panic("Unimplemented virtual mapping in KSSEG! ({:08X})\n", vaddr);
|
case 6: Util::panic("Unimplemented virtual mapping in KSSEG! ({:08X})\n", vaddr);
|
||||||
default:
|
default:
|
||||||
util::panic("Should never end up in default case in map_vaddr! ({:08X})\n", vaddr);
|
Util::panic("Should never end up in default case in map_vaddr! ({:08X})\n", vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -134,7 +134,7 @@ u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
case 0x1FC00800 ... 0xFFFFFFFF:
|
case 0x1FC00800 ... 0xFFFFFFFF:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
Util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,16 +152,16 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
|
return Util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
switch (paddr) {
|
||||||
case 0x00000000 ... 0x007FFFFF:
|
case 0x00000000 ... 0x007FFFFF:
|
||||||
return util::ReadAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr));
|
return Util::ReadAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr));
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
if ((paddr >> 12) & 1)
|
if ((paddr >> 12) & 1)
|
||||||
return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE);
|
return Util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE);
|
||||||
else
|
else
|
||||||
return util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE);
|
return Util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE);
|
||||||
case 0x04040000 ... 0x040FFFFF:
|
case 0x04040000 ... 0x040FFFFF:
|
||||||
case 0x04100000 ... 0x041FFFFF:
|
case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF:
|
case 0x04300000 ... 0x044FFFFF:
|
||||||
@@ -169,18 +169,18 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
return mmio.Read(paddr);
|
return mmio.Read(paddr);
|
||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
paddr = (paddr + 2) & ~3;
|
paddr = (paddr + 2) & ~3;
|
||||||
return util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask);
|
return Util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
|
return Util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
return be16toh(util::ReadAccess<u16>(pifRam, paddr - 0x1FC007C0));
|
return be16toh(Util::ReadAccess<u16>(pifRam, paddr - 0x1FC007C0));
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF:
|
case 0x04900000 ... 0x0FFFFFFF:
|
||||||
case 0x1FC00800 ... 0xFFFFFFFF:
|
case 0x1FC00800 ... 0xFFFFFFFF:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
Util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,29 +198,29 @@ u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return util::ReadAccess<u32>((u8*)pointer, offset);
|
return Util::ReadAccess<u32>((u8*)pointer, offset);
|
||||||
} else {
|
} else {
|
||||||
switch(paddr) {
|
switch(paddr) {
|
||||||
case 0x00000000 ... 0x007FFFFF:
|
case 0x00000000 ... 0x007FFFFF:
|
||||||
return util::ReadAccess<u32>(mmio.rdp.rdram.data(), paddr);
|
return Util::ReadAccess<u32>(mmio.rdp.rdram.data(), paddr);
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
if((paddr >> 12) & 1)
|
if((paddr >> 12) & 1)
|
||||||
return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE);
|
return Util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE);
|
||||||
else
|
else
|
||||||
return util::ReadAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
|
return Util::ReadAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
|
||||||
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF:
|
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF:
|
||||||
return mmio.Read(paddr);
|
return mmio.Read(paddr);
|
||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
return util::ReadAccess<u32>(cart.data(), paddr & romMask);
|
return Util::ReadAccess<u32>(cart.data(), paddr & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return util::ReadAccess<u32>(pifBootrom, paddr - 0x1FC00000);
|
return Util::ReadAccess<u32>(pifBootrom, paddr - 0x1FC00000);
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
return be32toh(util::ReadAccess<u32>(pifRam, paddr - 0x1FC007C0));
|
return be32toh(Util::ReadAccess<u32>(pifRam, paddr - 0x1FC007C0));
|
||||||
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0;
|
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,34 +238,34 @@ u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return util::ReadAccess<u64>((u8*)pointer, offset);
|
return Util::ReadAccess<u64>((u8*)pointer, offset);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
switch (paddr) {
|
||||||
case 0x00000000 ... 0x007FFFFF:
|
case 0x00000000 ... 0x007FFFFF:
|
||||||
return util::ReadAccess<u64>(mmio.rdp.rdram.data(), paddr);
|
return Util::ReadAccess<u64>(mmio.rdp.rdram.data(), paddr);
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
if ((paddr >> 12) & 1)
|
if ((paddr >> 12) & 1)
|
||||||
return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE);
|
return Util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE);
|
||||||
else
|
else
|
||||||
return util::ReadAccess<u64>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
|
return Util::ReadAccess<u64>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
|
||||||
case 0x04040000 ... 0x040FFFFF:
|
case 0x04040000 ... 0x040FFFFF:
|
||||||
case 0x04100000 ... 0x041FFFFF:
|
case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF:
|
case 0x04300000 ... 0x044FFFFF:
|
||||||
case 0x04500000 ... 0x048FFFFF:
|
case 0x04500000 ... 0x048FFFFF:
|
||||||
return mmio.Read(paddr);
|
return mmio.Read(paddr);
|
||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
return util::ReadAccess<u64>(cart.data(), paddr & romMask);
|
return Util::ReadAccess<u64>(cart.data(), paddr & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return util::ReadAccess<u64>(pifBootrom, paddr - 0x1FC00000);
|
return Util::ReadAccess<u64>(pifBootrom, paddr - 0x1FC00000);
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
return be64toh(util::ReadAccess<u64>(pifRam, paddr - 0x1FC007C0));
|
return be64toh(Util::ReadAccess<u64>(pifRam, paddr - 0x1FC007C0));
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF:
|
case 0x04900000 ... 0x0FFFFFFF:
|
||||||
case 0x1FC00800 ... 0xFFFFFFFF:
|
case 0x1FC00800 ... 0xFFFFFFFF:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})\n", paddr, (u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,21 +307,21 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
val = val << (8 * (3 - (paddr & 3)));
|
val = val << (8 * (3 - (paddr & 3)));
|
||||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
paddr = (paddr & DMEM_DSIZE) & ~3;
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
else
|
||||||
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||||
break;
|
break;
|
||||||
case 0x04040000 ... 0x040FFFFF:
|
case 0x04040000 ... 0x040FFFFF:
|
||||||
case 0x04100000 ... 0x041FFFFF:
|
case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF:
|
case 0x04300000 ... 0x044FFFFF:
|
||||||
case 0x04500000 ... 0x048FFFFF:
|
case 0x04500000 ... 0x048FFFFF:
|
||||||
util::panic("MMIO Write8!\n");
|
Util::panic("MMIO Write8!\n");
|
||||||
case 0x10000000 ... 0x13FFFFFF:
|
case 0x10000000 ... 0x13FFFFFF:
|
||||||
break;
|
break;
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
val = val << (8 * (3 - (paddr & 3)));
|
val = val << (8 * (3 - (paddr & 3)));
|
||||||
paddr = (paddr - 0x1FC007C0) & ~3;
|
paddr = (paddr - 0x1FC007C0) & ~3;
|
||||||
util::WriteAccess<u32>(pifRam, paddr, htobe32(val));
|
Util::WriteAccess<u32>(pifRam, paddr, htobe32(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
@@ -332,7 +332,7 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
case 0x80000000 ... 0xFFFFFFFF:
|
case 0x80000000 ... 0xFFFFFFFF:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 8-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
|
Util::panic("Unimplemented 8-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
|
||||||
(u64) regs.pc);
|
(u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -356,31 +356,31 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
offset &= ~3;
|
offset &= ~3;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
switch (paddr) {
|
||||||
case 0x00000000 ... 0x007FFFFF:
|
case 0x00000000 ... 0x007FFFFF:
|
||||||
util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
|
Util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val = val << (16 * !(paddr & 2));
|
val = val << (16 * !(paddr & 2));
|
||||||
paddr &= ~3;
|
paddr &= ~3;
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
else
|
||||||
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||||
break;
|
break;
|
||||||
case 0x04040000 ... 0x040FFFFF:
|
case 0x04040000 ... 0x040FFFFF:
|
||||||
case 0x04100000 ... 0x041FFFFF:
|
case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF:
|
case 0x04300000 ... 0x044FFFFF:
|
||||||
case 0x04500000 ... 0x048FFFFF:
|
case 0x04500000 ... 0x048FFFFF:
|
||||||
util::panic("MMIO Write16!\n");
|
Util::panic("MMIO Write16!\n");
|
||||||
case 0x10000000 ... 0x13FFFFFF:
|
case 0x10000000 ... 0x13FFFFFF:
|
||||||
break;
|
break;
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
val = val << (16 * !(paddr & 2));
|
val = val << (16 * !(paddr & 2));
|
||||||
paddr &= ~3;
|
paddr &= ~3;
|
||||||
util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val));
|
Util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
@@ -391,7 +391,7 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
case 0x80000000 ... 0xFFFFFFFF:
|
case 0x80000000 ... 0xFFFFFFFF:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 16-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
|
Util::panic("Unimplemented 16-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
|
||||||
(u64) regs.pc);
|
(u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,17 +410,17 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
util::WriteAccess<u32>((u8*)pointer, offset, val);
|
Util::WriteAccess<u32>((u8*)pointer, offset, val);
|
||||||
} else {
|
} else {
|
||||||
switch(paddr) {
|
switch(paddr) {
|
||||||
case 0x00000000 ... 0x007FFFFF:
|
case 0x00000000 ... 0x007FFFFF:
|
||||||
util::WriteAccess<u32>(mmio.rdp.rdram.data(), paddr, val);
|
Util::WriteAccess<u32>(mmio.rdp.rdram.data(), paddr, val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
if(paddr & 0x1000)
|
if(paddr & 0x1000)
|
||||||
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
else
|
||||||
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||||
break;
|
break;
|
||||||
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break;
|
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break;
|
||||||
@@ -434,16 +434,16 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case 0x13FF0020 ... 0x13FFFFFF:
|
case 0x13FF0020 ... 0x13FFFFFF:
|
||||||
util::WriteAccess<u32>(isviewer, paddr - 0x13FF0020, htobe32(val));
|
Util::WriteAccess<u32>(isviewer, paddr - 0x13FF0020, htobe32(val));
|
||||||
break;
|
break;
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val));
|
Util::WriteAccess<u32>(pifRam, paddr - 0x1FC007C0, htobe32(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF:
|
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF:
|
||||||
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break;
|
case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break;
|
||||||
default: util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc);
|
default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,28 +464,28 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
|||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||||
val >>= 32;
|
val >>= 32;
|
||||||
}
|
}
|
||||||
util::WriteAccess<u64>((u8*)pointer, offset, val);
|
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
switch (paddr) {
|
||||||
case 0x00000000 ... 0x007FFFFF:
|
case 0x00000000 ... 0x007FFFFF:
|
||||||
util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
|
Util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val >>= 32;
|
val >>= 32;
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
else
|
||||||
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||||
break;
|
break;
|
||||||
case 0x04040000 ... 0x040FFFFF:
|
case 0x04040000 ... 0x040FFFFF:
|
||||||
case 0x04100000 ... 0x041FFFFF:
|
case 0x04100000 ... 0x041FFFFF:
|
||||||
case 0x04300000 ... 0x044FFFFF:
|
case 0x04300000 ... 0x044FFFFF:
|
||||||
case 0x04500000 ... 0x048FFFFF:
|
case 0x04500000 ... 0x048FFFFF:
|
||||||
util::panic("MMIO Write64!\n");
|
Util::panic("MMIO Write64!\n");
|
||||||
case 0x10000000 ... 0x13FFFFFF:
|
case 0x10000000 ... 0x13FFFFFF:
|
||||||
break;
|
break;
|
||||||
case 0x1FC007C0 ... 0x1FC007FF:
|
case 0x1FC007C0 ... 0x1FC007FF:
|
||||||
util::WriteAccess<u64>(pifRam, paddr - 0x1FC007C0, htobe64(val));
|
Util::WriteAccess<u64>(pifRam, paddr - 0x1FC007C0, htobe64(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
@@ -496,7 +496,7 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
|||||||
case 0x80000000 ... 0xFFFFFFFF:
|
case 0x80000000 ... 0xFFFFFFFF:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
|
Util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val,
|
||||||
(u64) regs.pc);
|
(u64) regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ struct Mem {
|
|||||||
FILE *fp = fopen("rdram.dump", "wb");
|
FILE *fp = fopen("rdram.dump", "wb");
|
||||||
u8 *temp = (u8*)calloc(RDRAM_SIZE, 1);
|
u8 *temp = (u8*)calloc(RDRAM_SIZE, 1);
|
||||||
memcpy(temp, mmio.rdp.rdram.data(), RDRAM_SIZE);
|
memcpy(temp, mmio.rdp.rdram.data(), RDRAM_SIZE);
|
||||||
util::SwapBuffer32(RDRAM_SIZE, temp);
|
Util::SwapBuffer32(RDRAM_SIZE, temp);
|
||||||
fwrite(temp, 1, RDRAM_SIZE, fp);
|
fwrite(temp, 1, RDRAM_SIZE, fp);
|
||||||
free(temp);
|
free(temp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -58,7 +58,7 @@ struct Mem {
|
|||||||
FILE *fp = fopen("imem.bin", "wb");
|
FILE *fp = fopen("imem.bin", "wb");
|
||||||
u8 *temp = (u8*)calloc(IMEM_SIZE, 1);
|
u8 *temp = (u8*)calloc(IMEM_SIZE, 1);
|
||||||
memcpy(temp, mmio.rsp.imem, IMEM_SIZE);
|
memcpy(temp, mmio.rsp.imem, IMEM_SIZE);
|
||||||
util::SwapBuffer32(IMEM_SIZE, temp);
|
Util::SwapBuffer32(IMEM_SIZE, temp);
|
||||||
fwrite(temp, 1, IMEM_SIZE, fp);
|
fwrite(temp, 1, IMEM_SIZE, fp);
|
||||||
free(temp);
|
free(temp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -68,7 +68,7 @@ struct Mem {
|
|||||||
FILE *fp = fopen("dmem.dump", "wb");
|
FILE *fp = fopen("dmem.dump", "wb");
|
||||||
u8 *temp = (u8*)calloc(DMEM_SIZE, 1);
|
u8 *temp = (u8*)calloc(DMEM_SIZE, 1);
|
||||||
memcpy(temp, mmio.rsp.dmem, DMEM_SIZE);
|
memcpy(temp, mmio.rsp.dmem, DMEM_SIZE);
|
||||||
util::SwapBuffer32(DMEM_SIZE, temp);
|
Util::SwapBuffer32(DMEM_SIZE, temp);
|
||||||
fwrite(temp, 1, DMEM_SIZE, fp);
|
fwrite(temp, 1, DMEM_SIZE, fp);
|
||||||
free(temp);
|
free(temp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -107,7 +107,7 @@ private:
|
|||||||
cicType = CIC_NUS_6106_7106;
|
cicType = CIC_NUS_6106_7106;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::warn("Could not determine CIC TYPE! Checksum: {:08X} is unknown!\n", checksum);
|
Util::warn("Could not determine CIC TYPE! Checksum: {:08X} is unknown!\n", checksum);
|
||||||
cicType = UNKNOWN_CIC_TYPE;
|
cicType = UNKNOWN_CIC_TYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ auto RDP::Read(u32 addr) const -> u32 {
|
|||||||
case 0x04100018: return dpc.status.pipeBusy;
|
case 0x04100018: return dpc.status.pipeBusy;
|
||||||
case 0x0410001C: return dpc.tmem;
|
case 0x0410001C: return dpc.tmem;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled DP Command Registers read (addr: {:08X})\n", addr);
|
Util::panic("Unhandled DP Command Registers read (addr: {:08X})\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ void RDP::Write(MI& mi, Registers& regs, RSP& rsp, u32 addr, u32 val) {
|
|||||||
case 0x04100004: WriteEnd(mi, regs, rsp, val); break;
|
case 0x04100004: WriteEnd(mi, regs, rsp, val); break;
|
||||||
case 0x0410000C: WriteStatus(mi, regs, rsp, val); break;
|
case 0x0410000C: WriteStatus(mi, regs, rsp, val); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})\n", addr, val);
|
Util::panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})\n", addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,41 +74,41 @@ void RDP::WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val) {
|
|||||||
|
|
||||||
inline void logCommand(u8 cmd) {
|
inline void logCommand(u8 cmd) {
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case 0x08: util::print("Fill triangle\n"); break;
|
case 0x08: Util::print("Fill triangle\n"); break;
|
||||||
case 0x09: util::print("Fill, zbuf triangle\n"); break;
|
case 0x09: Util::print("Fill, zbuf triangle\n"); break;
|
||||||
case 0x0a: util::print("Texture triangle\n"); break;
|
case 0x0a: Util::print("Texture triangle\n"); break;
|
||||||
case 0x0b: util::print("Texture, zbuf triangle\n"); break;
|
case 0x0b: Util::print("Texture, zbuf triangle\n"); break;
|
||||||
case 0x0c: util::print("Shade triangle\n"); break;
|
case 0x0c: Util::print("Shade triangle\n"); break;
|
||||||
case 0x0d: util::print("Shade, zbuf triangle\n"); break;
|
case 0x0d: Util::print("Shade, zbuf triangle\n"); break;
|
||||||
case 0x0e: util::print("Shade, texture triangle\n"); break;
|
case 0x0e: Util::print("Shade, texture triangle\n"); break;
|
||||||
case 0x0f: util::print("Shade, texture, zbuf triangle\n"); break;
|
case 0x0f: Util::print("Shade, texture, zbuf triangle\n"); break;
|
||||||
case 0x24: util::print("Texture rectangle\n"); break;
|
case 0x24: Util::print("Texture rectangle\n"); break;
|
||||||
case 0x25: util::print("Texture rectangle flip\n"); break;
|
case 0x25: Util::print("Texture rectangle flip\n"); break;
|
||||||
case 0x26: util::print("Sync load\n"); break;
|
case 0x26: Util::print("Sync load\n"); break;
|
||||||
case 0x27: util::print("Sync pipe\n"); break;
|
case 0x27: Util::print("Sync pipe\n"); break;
|
||||||
case 0x28: util::print("Sync tile\n"); break;
|
case 0x28: Util::print("Sync tile\n"); break;
|
||||||
case 0x29: util::print("Sync full\n"); break;
|
case 0x29: Util::print("Sync full\n"); break;
|
||||||
case 0x2a: util::print("Set key gb\n"); break;
|
case 0x2a: Util::print("Set key gb\n"); break;
|
||||||
case 0x2b: util::print("Set key r\n"); break;
|
case 0x2b: Util::print("Set key r\n"); break;
|
||||||
case 0x2c: util::print("Set convert\n"); break;
|
case 0x2c: Util::print("Set convert\n"); break;
|
||||||
case 0x2d: util::print("Set scissor\n"); break;
|
case 0x2d: Util::print("Set scissor\n"); break;
|
||||||
case 0x2e: util::print("Set prim depth\n"); break;
|
case 0x2e: Util::print("Set prim depth\n"); break;
|
||||||
case 0x2f: util::print("Set other modes\n"); break;
|
case 0x2f: Util::print("Set other modes\n"); break;
|
||||||
case 0x30: util::print("Load TLUT\n"); break;
|
case 0x30: Util::print("Load TLUT\n"); break;
|
||||||
case 0x32: util::print("Set tile size\n"); break;
|
case 0x32: Util::print("Set tile size\n"); break;
|
||||||
case 0x33: util::print("Load block\n"); break;
|
case 0x33: Util::print("Load block\n"); break;
|
||||||
case 0x34: util::print("Load tile\n"); break;
|
case 0x34: Util::print("Load tile\n"); break;
|
||||||
case 0x35: util::print("Set tile\n"); break;
|
case 0x35: Util::print("Set tile\n"); break;
|
||||||
case 0x36: util::print("Fill rectangle\n"); break;
|
case 0x36: Util::print("Fill rectangle\n"); break;
|
||||||
case 0x37: util::print("Set fill color\n"); break;
|
case 0x37: Util::print("Set fill color\n"); break;
|
||||||
case 0x38: util::print("Set fog color\n"); break;
|
case 0x38: Util::print("Set fog color\n"); break;
|
||||||
case 0x39: util::print("Set blend color\n"); break;
|
case 0x39: Util::print("Set blend color\n"); break;
|
||||||
case 0x3a: util::print("Set prim color\n"); break;
|
case 0x3a: Util::print("Set prim color\n"); break;
|
||||||
case 0x3b: util::print("Set env color\n"); break;
|
case 0x3b: Util::print("Set env color\n"); break;
|
||||||
case 0x3c: util::print("Set combine\n"); break;
|
case 0x3c: Util::print("Set combine\n"); break;
|
||||||
case 0x3d: util::print("Set texture image\n"); break;
|
case 0x3d: Util::print("Set texture image\n"); break;
|
||||||
case 0x3e: util::print("Set mask image\n"); break;
|
case 0x3e: Util::print("Set mask image\n"); break;
|
||||||
case 0x3f: util::print("Set color image\n"); break;
|
case 0x3f: Util::print("Set color image\n"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +130,13 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
|
|||||||
if (len <= 0) return;
|
if (len <= 0) return;
|
||||||
|
|
||||||
if (len + (remaining_cmds * 4) > 0xFFFFF) {
|
if (len + (remaining_cmds * 4) > 0xFFFFF) {
|
||||||
util::panic("Too many RDP commands\n");
|
Util::panic("Too many RDP commands\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dpc.status.xbusDmemDma) {
|
if (dpc.status.xbusDmemDma) {
|
||||||
for (int i = 0; i < len; i += 4) {
|
for (int i = 0; i < len; i += 4) {
|
||||||
u32 cmd = util::ReadAccess<u32>(rsp.dmem, (current + i) & 0xFFF);
|
u32 cmd = Util::ReadAccess<u32>(rsp.dmem, (current + i) & 0xFFF);
|
||||||
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
|
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -144,7 +144,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < len; i += 4) {
|
for (int i = 0; i < len; i += 4) {
|
||||||
u32 cmd = util::ReadAccess<u32>(rdram.data(), current + i);
|
u32 cmd = Util::ReadAccess<u32>(rdram.data(), current + i);
|
||||||
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
|
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,39 +32,39 @@ void RSP::Reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void logRSP(const RSP& rsp, const u32 instr) {
|
inline void logRSP(const RSP& rsp, const u32 instr) {
|
||||||
util::print("{:04X} {:08X} ", rsp.oldPC, instr);
|
Util::print("{:04X} {:08X} ", rsp.oldPC, instr);
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
util::print("{:08X} ", (u32)rsp.gpr[i]);
|
Util::print("{:08X} ", (u32)rsp.gpr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
for (int e = 0; e < 8; e++) {
|
for (int e = 0; e < 8; e++) {
|
||||||
util::print("{:04X}", rsp.vpr[i].element[e]);
|
Util::print("{:04X}", rsp.vpr[i].element[e]);
|
||||||
}
|
}
|
||||||
util::print(" ");
|
Util::print(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int e = 0; e < 8; e++) {
|
for (int e = 0; e < 8; e++) {
|
||||||
util::print("{:04X}", rsp.acc.h.element[e]);
|
Util::print("{:04X}", rsp.acc.h.element[e]);
|
||||||
}
|
}
|
||||||
util::print(" ");
|
Util::print(" ");
|
||||||
|
|
||||||
for (int e = 0; e < 8; e++) {
|
for (int e = 0; e < 8; e++) {
|
||||||
util::print("{:04X}", rsp.acc.m.element[e]);
|
Util::print("{:04X}", rsp.acc.m.element[e]);
|
||||||
}
|
}
|
||||||
util::print(" ");
|
Util::print(" ");
|
||||||
|
|
||||||
for (int e = 0; e < 8; e++) {
|
for (int e = 0; e < 8; e++) {
|
||||||
util::print("{:04X}", rsp.acc.l.element[e]);
|
Util::print("{:04X}", rsp.acc.l.element[e]);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::print(" {:04X} {:04X} {:02X}\n", rsp.GetVCC(), rsp.GetVCO(), rsp.GetVCE());
|
Util::print(" {:04X} {:04X} {:02X}\n", rsp.GetVCC(), rsp.GetVCO(), rsp.GetVCE());
|
||||||
util::print("DMEM: {:02X}{:02X}\n", rsp.dmem[0x3c4], rsp.dmem[0x3c5]);
|
Util::print("DMEM: {:02X}{:02X}\n", rsp.dmem[0x3c4], rsp.dmem[0x3c5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSP::Step(Registers& regs, Mem& mem) {
|
void RSP::Step(Registers& regs, Mem& mem) {
|
||||||
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 & 0xFFC;
|
oldPC = pc & 0xFFC;
|
||||||
pc = nextPC & 0xFFC;
|
pc = nextPC & 0xFFC;
|
||||||
nextPC += 4;
|
nextPC += 4;
|
||||||
@@ -87,7 +87,7 @@ auto RSP::Read(u32 addr) -> u32{
|
|||||||
return AcquireSemaphore();
|
return AcquireSemaphore();
|
||||||
case 0x04080000: return pc & 0xFFC;
|
case 0x04080000: return pc & 0xFFC;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented SP register read {:08X}\n", addr);
|
Util::panic("Unimplemented SP register read {:08X}\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) {
|
|||||||
SetPC(value);
|
SetPC(value);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented SP register write {:08X}, val: {:08X}\n", addr, value);
|
Util::panic("Unimplemented SP register write {:08X}, val: {:08X}\n", addr, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,8 @@ void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
code.mov(code.rbp, (u64)®s.cop0.index);
|
code.and_(code.dword[code.rdi + offsetof(n64::Registers, cop0.index)], 0x3F);
|
||||||
code.and_(code.dword[code.rbp], 0x3F);
|
code.mov(code.rsi, code.dword[code.rdi]);
|
||||||
code.mov(code.rsi, code.dword[code.rbp]);
|
|
||||||
code.mov(code.rax, (u64)tlbw);
|
code.mov(code.rax, (u64)tlbw);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
@@ -57,10 +56,10 @@ void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.mov(code.rax, (u64)eret);
|
code.mov(code.rax, (u64)eret);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC);
|
default: Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7);
|
default: Util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ void eret(n64::Registers& regs) {
|
|||||||
void tlbr(n64::Registers& regs) {
|
void tlbr(n64::Registers& regs) {
|
||||||
u8 Index = regs.cop0.index & 0b111111;
|
u8 Index = regs.cop0.index & 0b111111;
|
||||||
if (Index >= 32) {
|
if (Index >= 32) {
|
||||||
util::panic("TLBR with TLB index {}", Index);
|
Util::panic("TLBR with TLB index {}", Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
TLBEntry entry = regs.cop0.tlb[Index];
|
TLBEntry entry = regs.cop0.tlb[Index];
|
||||||
@@ -54,7 +54,7 @@ void tlbw(n64::Registers& regs, int index_) {
|
|||||||
page_mask.mask = top | (top >> 1);
|
page_mask.mask = top | (top >> 1);
|
||||||
|
|
||||||
if(index_ >= 32) {
|
if(index_ >= 32) {
|
||||||
util::panic("TLBWI with TLB index {}", index_);
|
Util::panic("TLBWI with TLB index {}", index_);
|
||||||
}
|
}
|
||||||
|
|
||||||
regs.cop0.tlb[index_].entryHi.raw = regs.cop0.entryHi.raw;
|
regs.cop0.tlb[index_].entryHi.raw = regs.cop0.entryHi.raw;
|
||||||
|
|||||||
@@ -5,24 +5,6 @@
|
|||||||
namespace n64::JIT {
|
namespace n64::JIT {
|
||||||
bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
||||||
Xbyak::CodeGenerator& code = cpu.code;
|
Xbyak::CodeGenerator& code = cpu.code;
|
||||||
code.push(code.rbp);
|
|
||||||
code.mov(code.rbp, (u64)®s.cop0.status.raw);
|
|
||||||
code.mov(code.eax, code.dword[code.rbp]);
|
|
||||||
code.pop(code.rbp);
|
|
||||||
code.and_(code.eax, 0x20000000);
|
|
||||||
code.cmp(code.eax, 1);
|
|
||||||
code.je("NoException1");
|
|
||||||
|
|
||||||
code.mov(code.rdi, (u64)®s);
|
|
||||||
code.mov(code.rsi, (u64)ExceptionCode::CoprocessorUnusable);
|
|
||||||
code.mov(code.rdx, 1);
|
|
||||||
code.mov(code.rcx, 1);
|
|
||||||
code.mov(code.rax, (u64) FireException);
|
|
||||||
code.call(code.rax);
|
|
||||||
code.xor_(code.rax, code.rax);
|
|
||||||
code.ret();
|
|
||||||
|
|
||||||
code.L("NoException1");
|
|
||||||
|
|
||||||
u8 mask_sub = (instr >> 21) & 0x1F;
|
u8 mask_sub = (instr >> 21) & 0x1F;
|
||||||
u8 mask_fun = instr & 0x3F;
|
u8 mask_fun = instr & 0x3F;
|
||||||
@@ -46,7 +28,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
||||||
case 0x04:
|
case 0x04:
|
||||||
code.mov(code.rax, (u64)mtc1);
|
code.mov(code.rax, (u64)mtc1);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
@@ -60,7 +42,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
||||||
case 0x08:
|
case 0x08:
|
||||||
switch(mask_branch) {
|
switch(mask_branch) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -83,7 +65,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.mov(code.rax, (u64)bl);
|
code.mov(code.rax, (u64)bl);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
return true;
|
return true;
|
||||||
default: util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x10: // s
|
case 0x10: // s
|
||||||
@@ -153,7 +135,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
||||||
case 0x21:
|
case 0x21:
|
||||||
code.mov(code.rax, (u64)cvtds);
|
code.mov(code.rax, (u64)cvtds);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
@@ -246,7 +228,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.mov(code.rdx, NGT);
|
code.mov(code.rdx, NGT);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x11: // d
|
case 0x11: // d
|
||||||
@@ -320,7 +302,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x21:
|
case 0x21:
|
||||||
util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU Reserved instruction exception!\n");
|
||||||
case 0x24:
|
case 0x24:
|
||||||
code.mov(code.rax, (u64)cvtwd);
|
code.mov(code.rax, (u64)cvtwd);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
@@ -409,7 +391,7 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.mov(code.rdx, NGT);
|
code.mov(code.rdx, NGT);
|
||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x14: // w
|
case 0x14: // w
|
||||||
@@ -439,8 +421,8 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x24:
|
case 0x24:
|
||||||
util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
|
||||||
default: util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x15: // l
|
case 0x15: // l
|
||||||
@@ -470,13 +452,13 @@ bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
|
|||||||
code.call(code.rax);
|
code.call(code.rax);
|
||||||
break;
|
break;
|
||||||
case 0x24:
|
case 0x24:
|
||||||
util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
|
||||||
case 0x25:
|
case 0x25:
|
||||||
util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
|
Util::panic("[RECOMPILER] FPU reserved instruction exception!\n");
|
||||||
default: util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
default: Util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ void cfc1(n64::Registers& regs, u32 instr) {
|
|||||||
switch(fd) {
|
switch(fd) {
|
||||||
case 0: val = regs.cop1.fcr0; break;
|
case 0: val = regs.cop1.fcr0; break;
|
||||||
case 31: val = regs.cop1.fcr31.raw; break;
|
case 31: val = regs.cop1.fcr31.raw; break;
|
||||||
default: util::panic("Undefined CFC1 with rd != 0 or 31\n");
|
default: Util::panic("Undefined CFC1 with rd != 0 or 31\n");
|
||||||
}
|
}
|
||||||
regs.gpr[RT(instr)] = val;
|
regs.gpr[RT(instr)] = val;
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ void ctc1(n64::Registers& regs, u32 instr) {
|
|||||||
val &= 0x183ffff;
|
val &= 0x183ffff;
|
||||||
regs.cop1.fcr31.raw = val;
|
regs.cop1.fcr31.raw = val;
|
||||||
} break;
|
} break;
|
||||||
default: util::panic("Undefined CTC1 with rd != 0 or 31\n");
|
default: Util::panic("Undefined CTC1 with rd != 0 or 31\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ void Cop0::eret(Registers& regs) {
|
|||||||
void Cop0::tlbr(Registers& regs) {
|
void Cop0::tlbr(Registers& regs) {
|
||||||
u8 Index = index & 0b111111;
|
u8 Index = index & 0b111111;
|
||||||
if (Index >= 32) {
|
if (Index >= 32) {
|
||||||
util::panic("TLBR with TLB index {}", index);
|
Util::panic("TLBR with TLB index {}", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
TLBEntry entry = tlb[Index];
|
TLBEntry entry = tlb[Index];
|
||||||
@@ -55,7 +55,7 @@ void Cop0::tlbw(int index_, Registers& regs) {
|
|||||||
page_mask.mask = top | (top >> 1);
|
page_mask.mask = top | (top >> 1);
|
||||||
|
|
||||||
if(index_ >= 32) {
|
if(index_ >= 32) {
|
||||||
util::panic("TLBWI with TLB index {}", index_);
|
Util::panic("TLBWI with TLB index {}", index_);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlb[index_].entryHi.raw = entryHi.raw;
|
tlb[index_].entryHi.raw = entryHi.raw;
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ void Cop1::cfc1(Registers& regs, u32 instr) const {
|
|||||||
switch(fd) {
|
switch(fd) {
|
||||||
case 0: val = fcr0; break;
|
case 0: val = fcr0; break;
|
||||||
case 31: val = fcr31.raw; break;
|
case 31: val = fcr31.raw; break;
|
||||||
default: util::panic("Undefined CFC1 with rd != 0 or 31\n");
|
default: Util::panic("Undefined CFC1 with rd != 0 or 31\n");
|
||||||
}
|
}
|
||||||
regs.gpr[RT(instr)] = val;
|
regs.gpr[RT(instr)] = val;
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ void Cop1::ctc1(Registers& regs, u32 instr) {
|
|||||||
val &= 0x183ffff;
|
val &= 0x183ffff;
|
||||||
fcr31.raw = val;
|
fcr31.raw = val;
|
||||||
} break;
|
} break;
|
||||||
default: util::panic("Undefined CTC1 with rd != 0 or 31\n");
|
default: Util::panic("Undefined CTC1 with rd != 0 or 31\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void Interpreter::special(Registers& regs, u32 instr) {
|
|||||||
case 0x3E: dsrl32(regs, instr); break;
|
case 0x3E: dsrl32(regs, instr); break;
|
||||||
case 0x3F: dsra32(regs, instr); break;
|
case 0x3F: dsra32(regs, instr); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
|
Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ void Interpreter::regimm(Registers& regs, u32 instr) {
|
|||||||
case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break;
|
case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break;
|
case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
|
Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ void Interpreter::Exec(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
case 0x3D: regs.cop1.sdc1(regs, mem, instr); break;
|
case 0x3D: regs.cop1.sdc1(regs, mem, instr); break;
|
||||||
case 0x3F: sd(regs, mem, instr); break;
|
case 0x3F: sd(regs, mem, instr); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC);
|
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
dac.precision = bitrate + 1;
|
dac.precision = bitrate + 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled AI write at addr {:08X} with val {:08X}\n", addr, val);
|
Util::panic("Unhandled AI write at addr {:08X} with val {:08X}\n", addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ void AI::Step(Mem& mem, Registers& regs, int cpuCycles, float volumeL, float vol
|
|||||||
if(volumeR > 0 && volumeL > 0) {
|
if(volumeR > 0 && volumeL > 0) {
|
||||||
u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF;
|
u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF;
|
||||||
dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF);
|
dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF);
|
||||||
u32 data = util::ReadAccess<u32>(mem.mmio.rdp.rdram.data(), dmaAddr[0] & RDRAM_DSIZE);
|
u32 data = Util::ReadAccess<u32>(mem.mmio.rdp.rdram.data(), dmaAddr[0] & RDRAM_DSIZE);
|
||||||
s16 l = s16(data >> 16);
|
s16 l = s16(data >> 16);
|
||||||
s16 r = s16(data);
|
s16 r = s16(data);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ auto MI::Read(u32 paddr) const -> u32 {
|
|||||||
case 0x8: return miIntr.raw & 0x3F;
|
case 0x8: return miIntr.raw & 0x3F;
|
||||||
case 0xC: return miIntrMask.raw & 0x3F;
|
case 0xC: return miIntrMask.raw & 0x3F;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled MI[{:08X}] read\n", paddr);
|
Util::panic("Unhandled MI[{:08X}] read\n", paddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ void MI::Write(Registers& regs, u32 paddr, u32 val) {
|
|||||||
UpdateInterrupt(*this, regs);
|
UpdateInterrupt(*this, regs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled MI[{:08X}] write ({:08X})\n", val, paddr);
|
Util::panic("Unhandled MI[{:08X}] write ({:08X})\n", val, paddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ auto PI::Read(MI& mi, u32 addr) const -> u32 {
|
|||||||
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:
|
default:
|
||||||
util::panic("Unhandled PI[{:08X}] read\n", addr);
|
Util::panic("Unhandled PI[{:08X}] read\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,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);
|
||||||
//util::print("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})\n", len, dramAddr, cartAddr);
|
//Util::print("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})\n", len, dramAddr, cartAddr);
|
||||||
} break;
|
} break;
|
||||||
case 0x0460000C: {
|
case 0x0460000C: {
|
||||||
u32 len = (val & 0x00FFFFFF) + 1;
|
u32 len = (val & 0x00FFFFFF) + 1;
|
||||||
@@ -73,7 +73,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);
|
||||||
//util::print("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})\n", len, cart_addr, dram_addr);
|
//Util::print("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})\n", len, cart_addr, dram_addr);
|
||||||
} break;
|
} break;
|
||||||
case 0x04600010:
|
case 0x04600010:
|
||||||
if(val & 2) {
|
if(val & 2) {
|
||||||
@@ -84,7 +84,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
stub[(addr & 0xff) - 5] = val & 0xff;
|
stub[(addr & 0xff) - 5] = val & 0xff;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled PI[{:08X}] write ({:08X})\n", val, addr);
|
Util::panic("Unhandled PI[{:08X}] write ({:08X})\n", val, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
|
|||||||
res[3] = controller.joy_y;
|
res[3] = controller.joy_y;
|
||||||
break;
|
break;
|
||||||
case 2: case 3: res[0] = 0; break;
|
case 2: case 3: res[0] = 0; break;
|
||||||
default: util::panic("Unimplemented PIF command {}", cmd[2]);
|
default: Util::panic("Unimplemented PIF command {}", cmd[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
i += t + rlen;
|
i += t + rlen;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ auto RI::Read(u32 addr) const -> u32 {
|
|||||||
case 0x0470000C: return select;
|
case 0x0470000C: return select;
|
||||||
case 0x04700010: return refresh;
|
case 0x04700010: return refresh;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled RI[{:08X}] read\n", addr);
|
Util::panic("Unhandled RI[{:08X}] read\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ void RI::Write(u32 addr, u32 val) {
|
|||||||
case 0x0470000C: select = val; break;
|
case 0x0470000C: select = val; break;
|
||||||
case 0x04700010: refresh = val; break;
|
case 0x04700010: refresh = val; break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled RI[{:08X}] write with val {:08X}\n", addr, val);
|
Util::panic("Unhandled RI[{:08X}] write with val {:08X}\n", addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled SI[{:08X}] read\n", addr);
|
Util::panic("Unhandled SI[{:08X}] read\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ void DMA(Mem& mem, Registers& regs) {
|
|||||||
for(int i = 0; i < 64; i++) {
|
for(int i = 0; i < 64; i++) {
|
||||||
mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)];
|
mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)];
|
||||||
}
|
}
|
||||||
util::debug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr);
|
Util::debug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr);
|
||||||
ProcessPIFCommands(mem.pifRam, si.controller, mem);
|
ProcessPIFCommands(mem.pifRam, si.controller, mem);
|
||||||
}
|
}
|
||||||
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
|
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
|
||||||
@@ -67,13 +67,13 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
status.dmaBusy = true;
|
status.dmaBusy = true;
|
||||||
toDram = false;
|
toDram = false;
|
||||||
scheduler.enqueueRelative({SI_DMA_DELAY, DMA});
|
scheduler.enqueueRelative({SI_DMA_DELAY, DMA});
|
||||||
util::debug("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})\n", dramAddr, val & 0x1FFFFFFF);
|
Util::debug("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})\n", dramAddr, val & 0x1FFFFFFF);
|
||||||
} break;
|
} break;
|
||||||
case 0x04800018:
|
case 0x04800018:
|
||||||
InterruptLower(mem.mmio.mi, regs, Interrupt::SI);
|
InterruptLower(mem.mmio.mi, regs, Interrupt::SI);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unhandled SI[%08X] write (%08X)\n", addr, val);
|
Util::panic("Unhandled SI[%08X] write (%08X)\n", addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ u32 VI::Read(u32 paddr) const {
|
|||||||
case 0x04400030: return xscale.raw;
|
case 0x04400030: return xscale.raw;
|
||||||
case 0x04400034: return yscale.raw;
|
case 0x04400034: return yscale.raw;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented VI[%08X] read\n", paddr);
|
Util::panic("Unimplemented VI[%08X] read\n", paddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
|
|||||||
case 0x04400030: xscale.raw = val; break;
|
case 0x04400030: xscale.raw = val; break;
|
||||||
case 0x04400034: yscale.raw = val; break;
|
case 0x04400034: yscale.raw = val; break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented VI[%08X] write (%08X)\n", paddr, val);
|
Util::panic("Unimplemented VI[%08X] write (%08X)\n", paddr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ u32 Cop0::GetReg32(u8 addr) {
|
|||||||
case 23: case 24: case 25:
|
case 23: case 24: case 25:
|
||||||
case 31: return openbus;
|
case 31: return openbus;
|
||||||
default:
|
default:
|
||||||
util::panic("Unsupported word read from COP0 register {}\n", index);
|
Util::panic("Unsupported word read from COP0 register {}\n", index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ u64 Cop0::GetReg64(u8 addr) {
|
|||||||
case 23: case 24: case 25:
|
case 23: case 24: case 25:
|
||||||
case 31: return openbus;
|
case 31: return openbus;
|
||||||
default:
|
default:
|
||||||
util::panic("Unsupported word read from COP0 register {}\n", index);
|
Util::panic("Unsupported word read from COP0 register {}\n", index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ void Cop0::SetReg32(u8 addr, u32 value) {
|
|||||||
case 23: case 24: case 25:
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ void Cop0::SetReg64(u8 addr, u64 value) {
|
|||||||
case COP0_REG_LLADDR: LLAddr = value; break;
|
case COP0_REG_LLADDR: LLAddr = value; break;
|
||||||
case COP0_REG_ERROREPC: ErrorEPC = (s64)value; break;
|
case COP0_REG_ERROREPC: ErrorEPC = (s64)value; break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unsupported word write to COP0 register {}\n", addr);
|
Util::panic("Unsupported word write to COP0 register {}\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ void FireException(Registers& regs, ExceptionCode code, int cop, bool useOldPC)
|
|||||||
regs.cop0.cause.exceptionCode = static_cast<u8>(code);
|
regs.cop0.cause.exceptionCode = static_cast<u8>(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 ExceptionCode::Interrupt: case ExceptionCode::TLBModification:
|
||||||
@@ -285,7 +285,7 @@ void FireException(Registers& regs, ExceptionCode code, int cop, bool useOldPC)
|
|||||||
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", static_cast<u8>(code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,7 +303,7 @@ void HandleTLBException(Registers& regs, u64 vaddr) {
|
|||||||
|
|
||||||
ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType) {
|
ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType) {
|
||||||
switch(error) {
|
switch(error) {
|
||||||
case NONE: util::panic("Getting TLB exception with error NONE\n");
|
case NONE: Util::panic("Getting TLB exception with error NONE\n");
|
||||||
case INVALID: case MISS:
|
case INVALID: case MISS:
|
||||||
return accessType == LOAD ?
|
return accessType == LOAD ?
|
||||||
ExceptionCode::TLBLoad : ExceptionCode::TLBStore;
|
ExceptionCode::TLBLoad : ExceptionCode::TLBStore;
|
||||||
@@ -313,7 +313,7 @@ ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType) {
|
|||||||
return accessType == LOAD ?
|
return accessType == LOAD ?
|
||||||
ExceptionCode::AddressErrorLoad : ExceptionCode::AddressErrorStore;
|
ExceptionCode::AddressErrorLoad : ExceptionCode::AddressErrorStore;
|
||||||
default:
|
default:
|
||||||
util::panic("Getting TLB exception for unknown error code! ({})\n", error);
|
Util::panic("Getting TLB exception for unknown error code! ({})\n", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,10 +332,10 @@ void Cop0::decode(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
case 0x06: tlbw(GetRandom(), regs); break;
|
case 0x06: tlbw(GetRandom(), regs); break;
|
||||||
case 0x08: tlbp(regs); break;
|
case 0x08: tlbp(regs); break;
|
||||||
case 0x18: eret(regs); break;
|
case 0x18: eret(regs); break;
|
||||||
default: util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC);
|
default: Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7);
|
default: Util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
|||||||
case 1: cpu.b(regs, instr, regs.cop1.fcr31.compare); break;
|
case 1: cpu.b(regs, instr, regs.cop1.fcr31.compare); break;
|
||||||
case 2: cpu.bl(regs, instr, !regs.cop1.fcr31.compare); break;
|
case 2: cpu.bl(regs, instr, !regs.cop1.fcr31.compare); break;
|
||||||
case 3: cpu.bl(regs, instr, regs.cop1.fcr31.compare); break;
|
case 3: cpu.bl(regs, instr, regs.cop1.fcr31.compare); break;
|
||||||
default: util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x10: // s
|
case 0x10: // s
|
||||||
@@ -82,7 +82,7 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
|||||||
case 0x3D: ccond<float>(regs, instr, NGE); break;
|
case 0x3D: ccond<float>(regs, instr, NGE); break;
|
||||||
case 0x3E: ccond<float>(regs, instr, LE); break;
|
case 0x3E: ccond<float>(regs, instr, LE); break;
|
||||||
case 0x3F: ccond<float>(regs, instr, NGT); break;
|
case 0x3F: ccond<float>(regs, instr, NGT); break;
|
||||||
default: util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x11: // d
|
case 0x11: // d
|
||||||
@@ -125,7 +125,7 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
|||||||
case 0x3D: ccond<double>(regs, instr, NGE); break;
|
case 0x3D: ccond<double>(regs, instr, NGE); break;
|
||||||
case 0x3E: ccond<double>(regs, instr, LE); break;
|
case 0x3E: ccond<double>(regs, instr, LE); break;
|
||||||
case 0x3F: ccond<double>(regs, instr, NGT); break;
|
case 0x3F: ccond<double>(regs, instr, NGT); break;
|
||||||
default: util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x14: // w
|
case 0x14: // w
|
||||||
@@ -139,7 +139,7 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
|||||||
case 0x24:
|
case 0x24:
|
||||||
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x15: // l
|
case 0x15: // l
|
||||||
@@ -156,10 +156,10 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
|||||||
case 0x25:
|
case 0x25:
|
||||||
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
FireException(regs, ExceptionCode::ReservedInstruction, 1, true);
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
default: Util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
default: Util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
namespace n64 {
|
namespace n64 {
|
||||||
inline void special(MI& mi, Registers& regs, RSP& rsp, u32 instr) {
|
inline void special(MI& mi, Registers& regs, RSP& rsp, u32 instr) {
|
||||||
u8 mask = instr & 0x3f;
|
u8 mask = instr & 0x3f;
|
||||||
//util::print("rsp special {:02X}\n", mask);
|
//Util::print("rsp special {:02X}\n", mask);
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
if(instr != 0) {
|
if(instr != 0) {
|
||||||
@@ -41,25 +41,25 @@ inline void special(MI& mi, Registers& regs, RSP& rsp, u32 instr) {
|
|||||||
case 0x27: rsp.nor(instr); break;
|
case 0x27: rsp.nor(instr); break;
|
||||||
case 0x2A: rsp.slt(instr); break;
|
case 0x2A: rsp.slt(instr); break;
|
||||||
case 0x2B: rsp.sltu(instr); break;
|
case 0x2B: rsp.sltu(instr); break;
|
||||||
default: util::panic("Unhandled RSP special instruction ({:06b})\n", mask);
|
default: Util::panic("Unhandled RSP special instruction ({:06b})\n", mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void regimm(RSP& rsp, u32 instr) {
|
inline void regimm(RSP& rsp, u32 instr) {
|
||||||
u8 mask = ((instr >> 16) & 0x1F);
|
u8 mask = ((instr >> 16) & 0x1F);
|
||||||
//util::print("rsp regimm {:02X}\n", mask);
|
//Util::print("rsp regimm {:02X}\n", mask);
|
||||||
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;
|
||||||
case 0x10: rsp.blink(instr, (s32)rsp.gpr[RS(instr)] < 0); break;
|
case 0x10: rsp.blink(instr, (s32)rsp.gpr[RS(instr)] < 0); break;
|
||||||
case 0x11: rsp.blink(instr, (s32)rsp.gpr[RS(instr)] >= 0); break;
|
case 0x11: rsp.blink(instr, (s32)rsp.gpr[RS(instr)] >= 0); break;
|
||||||
default: util::panic("Unhandled RSP regimm instruction ({:05b})\n", mask);
|
default: Util::panic("Unhandled RSP regimm instruction ({:05b})\n", mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lwc2(RSP& rsp, u32 instr) {
|
inline void lwc2(RSP& rsp, u32 instr) {
|
||||||
u8 mask = (instr >> 11) & 0x1F;
|
u8 mask = (instr >> 11) & 0x1F;
|
||||||
//util::print("lwc2 {:02X}\n", mask);
|
//Util::print("lwc2 {:02X}\n", mask);
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00: rsp.lbv(instr); break;
|
case 0x00: rsp.lbv(instr); break;
|
||||||
case 0x01: rsp.lsv(instr); break;
|
case 0x01: rsp.lsv(instr); break;
|
||||||
@@ -71,13 +71,13 @@ inline void lwc2(RSP& rsp, u32 instr) {
|
|||||||
case 0x07: rsp.luv(instr); break;
|
case 0x07: rsp.luv(instr); break;
|
||||||
case 0x0A: break;
|
case 0x0A: break;
|
||||||
case 0x0B: rsp.ltv(instr); break;
|
case 0x0B: rsp.ltv(instr); break;
|
||||||
default: util::panic("Unhandled RSP LWC2 {:05b}\n", mask);
|
default: Util::panic("Unhandled RSP LWC2 {:05b}\n", mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swc2(RSP& rsp, u32 instr) {
|
inline void swc2(RSP& rsp, u32 instr) {
|
||||||
u8 mask = (instr >> 11) & 0x1F;
|
u8 mask = (instr >> 11) & 0x1F;
|
||||||
//util::print("swc2 {:02X}\n", mask);
|
//Util::print("swc2 {:02X}\n", mask);
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00: rsp.sbv(instr); break;
|
case 0x00: rsp.sbv(instr); break;
|
||||||
case 0x01: rsp.ssv(instr); break;
|
case 0x01: rsp.ssv(instr); break;
|
||||||
@@ -88,14 +88,14 @@ inline void swc2(RSP& rsp, u32 instr) {
|
|||||||
case 0x07: rsp.suv(instr); break;
|
case 0x07: rsp.suv(instr); break;
|
||||||
case 0x0A: rsp.swv(instr); break;
|
case 0x0A: rsp.swv(instr); break;
|
||||||
case 0x0B: rsp.stv(instr); break;
|
case 0x0B: rsp.stv(instr); break;
|
||||||
default: util::panic("Unhandled RSP SWC2 {:05b}\n", mask);
|
default: Util::panic("Unhandled RSP SWC2 {:05b}\n", mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void cop2(RSP& rsp, u32 instr) {
|
inline void cop2(RSP& rsp, u32 instr) {
|
||||||
u8 mask = instr & 0x3F;
|
u8 mask = instr & 0x3F;
|
||||||
u8 mask_sub = (instr >> 21) & 0x1F;
|
u8 mask_sub = (instr >> 21) & 0x1F;
|
||||||
//util::print("Cop2 {:02X}\n", mask);
|
//Util::print("Cop2 {:02X}\n", mask);
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
if((instr >> 25) & 1) {
|
if((instr >> 25) & 1) {
|
||||||
@@ -106,7 +106,7 @@ inline void cop2(RSP& rsp, u32 instr) {
|
|||||||
case 0x02: rsp.cfc2(instr); break;
|
case 0x02: rsp.cfc2(instr); break;
|
||||||
case 0x04: rsp.mtc2(instr); break;
|
case 0x04: rsp.mtc2(instr); break;
|
||||||
case 0x06: rsp.ctc2(instr); break;
|
case 0x06: rsp.ctc2(instr); break;
|
||||||
default: util::panic("Unhandled RSP COP2 sub ({:05b})\n", mask_sub);
|
default: Util::panic("Unhandled RSP COP2 sub ({:05b})\n", mask_sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -150,7 +150,7 @@ inline void cop2(RSP& rsp, u32 instr) {
|
|||||||
case 0x33: rsp.vmov(instr); break;
|
case 0x33: rsp.vmov(instr); break;
|
||||||
case 0x34: rsp.vrsq(instr); break;
|
case 0x34: rsp.vrsq(instr); break;
|
||||||
case 0x37: case 0x3F: break;
|
case 0x37: case 0x3F: break;
|
||||||
default: util::panic("Unhandled RSP COP2 ({:06b})\n", mask);
|
default: Util::panic("Unhandled RSP COP2 ({:06b})\n", mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,15 +159,15 @@ inline void cop0(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
MMIO& mmio = mem.mmio;
|
MMIO& mmio = mem.mmio;
|
||||||
RSP& rsp = mmio.rsp;
|
RSP& rsp = mmio.rsp;
|
||||||
RDP& rdp = mmio.rdp;
|
RDP& rdp = mmio.rdp;
|
||||||
//util::print("Cop0 {:02X}\n", mask);
|
//Util::print("Cop0 {:02X}\n", mask);
|
||||||
if((instr & 0x7FF) == 0) {
|
if((instr & 0x7FF) == 0) {
|
||||||
switch (mask) {
|
switch (mask) {
|
||||||
case 0x00: rsp.mfc0(rdp, instr); break;
|
case 0x00: rsp.mfc0(rdp, instr); break;
|
||||||
case 0x04: rsp.mtc0(regs, mem, instr); break;
|
case 0x04: rsp.mtc0(regs, mem, instr); break;
|
||||||
default: util::panic("Unhandled RSP COP0 ({:05b})\n", mask);
|
default: Util::panic("Unhandled RSP COP0 ({:05b})\n", mask);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
util::panic("RSP COP0 unknown {:08X}\n", instr);
|
Util::panic("RSP COP0 unknown {:08X}\n", instr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ void RSP::Exec(Registers ®s, Mem& mem, u32 instr) {
|
|||||||
MMIO& mmio = mem.mmio;
|
MMIO& mmio = mem.mmio;
|
||||||
RDP& rdp = mmio.rdp;
|
RDP& rdp = mmio.rdp;
|
||||||
MI& mi = mmio.mi;
|
MI& mi = mmio.mi;
|
||||||
//util::print("RSP {:02X}\n", mask);
|
//Util::print("RSP {:02X}\n", mask);
|
||||||
switch(mask) {
|
switch(mask) {
|
||||||
case 0x00: special(mi, regs, *this, instr); break;
|
case 0x00: special(mi, regs, *this, instr); break;
|
||||||
case 0x01: regimm(*this, instr); break;
|
case 0x01: regimm(*this, instr); break;
|
||||||
@@ -211,11 +211,11 @@ void RSP::Exec(Registers ®s, Mem& mem, u32 instr) {
|
|||||||
FILE *fp = fopen("imem.bin", "wb");
|
FILE *fp = fopen("imem.bin", "wb");
|
||||||
u8 *temp = (u8*)calloc(IMEM_SIZE, 1);
|
u8 *temp = (u8*)calloc(IMEM_SIZE, 1);
|
||||||
memcpy(temp, imem, IMEM_SIZE);
|
memcpy(temp, imem, IMEM_SIZE);
|
||||||
util::SwapBuffer32(IMEM_SIZE, temp);
|
Util::SwapBuffer32(IMEM_SIZE, temp);
|
||||||
fwrite(temp, 1, IMEM_SIZE, fp);
|
fwrite(temp, 1, IMEM_SIZE, fp);
|
||||||
free(temp);
|
free(temp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
util::panic("Unhandled RSP instruction ({:06b}, {:04X})\n", mask, oldPC);
|
Util::panic("Unhandled RSP instruction ({:06b}, {:04X})\n", mask, oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ inline auto GetCop0Reg(RSP& rsp, RDP& rdp, u8 index) -> u32{
|
|||||||
case 13: return rdp.dpc.status.cmdBusy;
|
case 13: return rdp.dpc.status.cmdBusy;
|
||||||
case 14: return rdp.dpc.status.pipeBusy;
|
case 14: return rdp.dpc.status.pipeBusy;
|
||||||
case 15: return rdp.dpc.status.tmemBusy;
|
case 15: return rdp.dpc.status.tmemBusy;
|
||||||
default: util::panic("Unhandled RSP COP0 register read at index {}\n", index);
|
default: Util::panic("Unhandled RSP COP0 register read at index {}\n", index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,13 +70,13 @@ inline void SetCop0Reg(Registers& regs, Mem& mem, u8 index, u32 val) {
|
|||||||
if(val == 0) {
|
if(val == 0) {
|
||||||
ReleaseSemaphore(rsp);
|
ReleaseSemaphore(rsp);
|
||||||
} else {
|
} else {
|
||||||
util::panic("Write with non-zero value to RSP_COP0_RESERVED ({})\n", val);
|
Util::panic("Write with non-zero value to RSP_COP0_RESERVED ({})\n", val);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8: rdp.WriteStart(val); break;
|
case 8: rdp.WriteStart(val); break;
|
||||||
case 9: rdp.WriteEnd(mi, regs, rsp, val); break;
|
case 9: rdp.WriteEnd(mi, regs, rsp, val); break;
|
||||||
case 11: rdp.WriteStatus(mi, regs, rsp, val); break;
|
case 11: rdp.WriteStatus(mi, regs, rsp, val); break;
|
||||||
default: util::panic("Unhandled RSP COP0 register write at index {}\n", index);
|
default: Util::panic("Unhandled RSP COP0 register write at index {}\n", index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,7 +735,7 @@ void RSP::vmov(u32 instr) {
|
|||||||
se = (e & 0b111) | (vs & 0b000);
|
se = (e & 0b111) | (vs & 0b000);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util::panic("VMOV: This should be unreachable!\n");
|
Util::panic("VMOV: This should be unreachable!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 de = vs & 7;
|
u8 de = vs & 7;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
App::App() : window(core) {
|
App::App() : window(core) {
|
||||||
DiscordEventHandlers handlers{};
|
DiscordEventHandlers handlers{};
|
||||||
Discord_Initialize("1049669178124148806", &handlers, 1, nullptr);
|
Discord_Initialize("1049669178124148806", &handlers, 1, nullptr);
|
||||||
util::UpdateRPC(util::Idling);
|
Util::UpdateRPC(Util::Idling);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::Run() {
|
void App::Run() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
App();
|
App();
|
||||||
~App() { util::ClearRPC(); }
|
~App() { Util::ClearRPC(); }
|
||||||
void Run();
|
void Run();
|
||||||
inline void LoadROM(const std::string& path) {
|
inline void LoadROM(const std::string& path) {
|
||||||
window.LoadROM(core, path);
|
window.LoadROM(core, path);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <RomHelpers.hpp>
|
#include <RomHelpers.hpp>
|
||||||
#include <File.hpp>
|
#include <File.hpp>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
@@ -25,12 +26,12 @@ GameList::GameList(const std::string& path) {
|
|||||||
file.unsetf(std::ios::skipws);
|
file.unsetf(std::ios::skipws);
|
||||||
|
|
||||||
if(!file.is_open()) {
|
if(!file.is_open()) {
|
||||||
util::panic("Unable to open {}!", filename);
|
Util::panic("Unable to open {}!", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
file.seekg(0, std::ios::end);
|
file.seekg(0, std::ios::end);
|
||||||
auto size = file.tellg();
|
auto size = file.tellg();
|
||||||
auto sizeAdjusted = util::NextPow2(size);
|
auto sizeAdjusted = Util::NextPow2(size);
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
std::fill(rom.begin(), rom.end(), 0);
|
std::fill(rom.begin(), rom.end(), 0);
|
||||||
@@ -39,7 +40,7 @@ GameList::GameList(const std::string& path) {
|
|||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
u32 crc{};
|
u32 crc{};
|
||||||
util::GetRomCRC(sizeAdjusted, rom.data(), crc);
|
Util::GetRomCRC(sizeAdjusted, rom.data(), crc);
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ GameList::GameList(const std::string& path) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
gameDbFile.close();
|
gameDbFile.close();
|
||||||
|
threadDone = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
searchThread.detach();
|
searchThread.detach();
|
||||||
@@ -93,10 +95,9 @@ bool GameList::RenderWidget(float mainMenuBarHeight, std::string& rom) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static ImGuiTableFlags flags =
|
static ImGuiTableFlags flags =
|
||||||
ImGuiTableFlags_Resizable
|
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
|
||||||
| ImGuiTableFlags_RowBg
|
| ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody
|
||||||
| ImGuiTableFlags_BordersOuterV
|
| ImGuiTableFlags_ScrollY;
|
||||||
| ImGuiTableFlags_SizingStretchProp;
|
|
||||||
|
|
||||||
bool toOpen = false;
|
bool toOpen = false;
|
||||||
if (ImGui::BeginTable("Games List", 4, flags)) {
|
if (ImGui::BeginTable("Games List", 4, flags)) {
|
||||||
@@ -104,6 +105,7 @@ bool GameList::RenderWidget(float mainMenuBarHeight, std::string& rom) {
|
|||||||
ImGui::TableSetupColumn("Region");
|
ImGui::TableSetupColumn("Region");
|
||||||
ImGui::TableSetupColumn("Status");
|
ImGui::TableSetupColumn("Status");
|
||||||
ImGui::TableSetupColumn("Size");
|
ImGui::TableSetupColumn("Size");
|
||||||
|
ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
enum GameInfoID {
|
||||||
|
Name_ID,
|
||||||
|
Region_ID,
|
||||||
|
Size_ID,
|
||||||
|
Status_ID
|
||||||
|
};
|
||||||
|
|
||||||
struct GameInfo {
|
struct GameInfo {
|
||||||
std::string name, region, size, status, path;
|
std::string name, region, size, status, path;
|
||||||
@@ -15,4 +23,5 @@ struct GameList {
|
|||||||
[[nodiscard]] std::vector<GameInfo> GetGamesList() const { return gamesList; }
|
[[nodiscard]] std::vector<GameInfo> GetGamesList() const { return gamesList; }
|
||||||
private:
|
private:
|
||||||
std::vector<GameInfo> gamesList{}, notMatch{};
|
std::vector<GameInfo> gamesList{}, notMatch{};
|
||||||
|
std::atomic_bool threadDone = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Settings::Settings(n64::Core& core) {
|
|||||||
} else if(cpuType == "interpreter") {
|
} else if(cpuType == "interpreter") {
|
||||||
core.cpuType = n64::CpuType::Interpreter;
|
core.cpuType = n64::CpuType::Interpreter;
|
||||||
} else {
|
} else {
|
||||||
util::panic("Unrecognized cpu type: {}\n", cpuType);
|
Util::panic("Unrecognized cpu type: {}\n", cpuType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
settingsFile.clear();
|
settingsFile.clear();
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ void Window::InitSDL() {
|
|||||||
windowID = SDL_GetWindowID(window);
|
windowID = SDL_GetWindowID(window);
|
||||||
|
|
||||||
if(volkInitialize() != VK_SUCCESS) {
|
if(volkInitialize() != VK_SUCCESS) {
|
||||||
util::panic("Failed to load Volk!");
|
Util::panic("Failed to load Volk!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_vk_result(VkResult err) {
|
static void check_vk_result(VkResult err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
util::panic("[vulkan] Error: VkResult = {}", err);
|
Util::panic("[vulkan] Error: VkResult = {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ void Window::LoadROM(n64::Core& core, const std::string &path) {
|
|||||||
gameName = fs::path(path).stem().string();
|
gameName = fs::path(path).stem().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
util::UpdateRPC(util::Playing, gameName);
|
Util::UpdateRPC(Util::Playing, gameName);
|
||||||
windowTitle = "Gadolinium - " + gameName;
|
windowTitle = "Gadolinium - " + gameName;
|
||||||
shadowWindowTitle = windowTitle;
|
shadowWindowTitle = windowTitle;
|
||||||
renderGameList = false;
|
renderGameList = false;
|
||||||
@@ -215,7 +215,7 @@ float Window::Render(n64::Core& core) {
|
|||||||
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
||||||
if (result == NFD_OKAY) {
|
if (result == NFD_OKAY) {
|
||||||
LoadROM(core, outpath);
|
LoadROM(core, outpath);
|
||||||
util::UpdateRPC(util::Playing, gameName);
|
Util::UpdateRPC(Util::Playing, gameName);
|
||||||
NFD_FreePath(outpath);
|
NFD_FreePath(outpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +241,7 @@ float Window::Render(n64::Core& core) {
|
|||||||
renderGameList = true;
|
renderGameList = true;
|
||||||
windowTitle = "Gadolinium";
|
windowTitle = "Gadolinium";
|
||||||
core.rom.clear();
|
core.rom.clear();
|
||||||
util::UpdateRPC(util::Idling);
|
Util::UpdateRPC(Util::Idling);
|
||||||
SDL_SetWindowTitle(window, windowTitle.c_str());
|
SDL_SetWindowTitle(window, windowTitle.c_str());
|
||||||
core.Stop();
|
core.Stop();
|
||||||
}
|
}
|
||||||
@@ -250,10 +250,10 @@ float Window::Render(n64::Core& core) {
|
|||||||
if(core.pause) {
|
if(core.pause) {
|
||||||
shadowWindowTitle = windowTitle;
|
shadowWindowTitle = windowTitle;
|
||||||
windowTitle += " | Paused";
|
windowTitle += " | Paused";
|
||||||
util::UpdateRPC(util::Paused, gameName);
|
Util::UpdateRPC(Util::Paused, gameName);
|
||||||
} else {
|
} else {
|
||||||
windowTitle = shadowWindowTitle;
|
windowTitle = shadowWindowTitle;
|
||||||
util::UpdateRPC(util::Playing, gameName);
|
Util::UpdateRPC(Util::Playing, gameName);
|
||||||
}
|
}
|
||||||
SDL_SetWindowTitle(window, windowTitle.c_str());
|
SDL_SetWindowTitle(window, windowTitle.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace util {
|
namespace Util {
|
||||||
inline auto ReadFileBinary(const std::string& path, u32** buf) {
|
inline auto ReadFileBinary(const std::string& path, u32** buf) {
|
||||||
std::ifstream file(path, std::ios::binary);
|
std::ifstream file(path, std::ios::binary);
|
||||||
file.unsetf(std::ios::skipws);
|
file.unsetf(std::ios::skipws);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <portable_endian_bswap.h>
|
#include <portable_endian_bswap.h>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace util {
|
namespace Util {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T ReadAccess(u8 *data, u32 index) {
|
inline T ReadAccess(u8 *data, u32 index) {
|
||||||
if constexpr (sizeof(T) == 1) {
|
if constexpr (sizeof(T) == 1) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/color.h>
|
#include <fmt/color.h>
|
||||||
|
|
||||||
namespace util {
|
namespace Util {
|
||||||
enum MessageType : u8 {
|
enum MessageType : u8 {
|
||||||
Info, Debug, Warn, Error
|
Info, Debug, Warn, Error
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user