mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 22:25:41 +12:00
Proper KVM/Dynarmic split
This commit is contained in:
parent
b5371dc66c
commit
2057e0c447
6 changed files with 154 additions and 105 deletions
|
@ -35,12 +35,16 @@ if(CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x
|
||||||
#set(DYNARMIC_NO_BUNDLED_FMT ON)
|
#set(DYNARMIC_NO_BUNDLED_FMT ON)
|
||||||
set(DYNARMIC_FRONTENDS "A32" CACHE STRING "")
|
set(DYNARMIC_FRONTENDS "A32" CACHE STRING "")
|
||||||
add_subdirectory(third_party/dynarmic)
|
add_subdirectory(third_party/dynarmic)
|
||||||
|
add_compile_definitions(CPU_DYNARMIC)
|
||||||
else()
|
else()
|
||||||
|
add_compile_definitions(CPU_KVM)
|
||||||
message(FATAL_ERROR "THIS IS NOT x64 WAIT FOR THE KVM IMPLEMENTATION")
|
message(FATAL_ERROR "THIS IS NOT x64 WAIT FOR THE KVM IMPLEMENTATION")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SOURCE_FILES src/main.cpp src/emulator.cpp)
|
set(SOURCE_FILES src/main.cpp src/emulator.cpp src/cpu/cpu_dynarmic.cpp)
|
||||||
set(INCLUDE_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp include/opengl.hpp)
|
set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/opengl.hpp include/termcolor.hpp
|
||||||
|
include/cpu.hpp include/cpu_dynarmic.hpp
|
||||||
|
)
|
||||||
|
|
||||||
set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp
|
set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp
|
||||||
third_party/imgui/imgui_draw.cpp
|
third_party/imgui/imgui_draw.cpp
|
||||||
|
@ -50,9 +54,10 @@ set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp
|
||||||
third_party/gl3w/gl3w.cpp
|
third_party/gl3w/gl3w.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#add_library(Alber ${HEADER_FILES})
|
||||||
|
source_group("Header Files\\Core" FILES ${HEADER_FILES})
|
||||||
source_group("Source Files\\Core" FILES ${SOURCE_FILES})
|
source_group("Source Files\\Core" FILES ${SOURCE_FILES})
|
||||||
source_group("Include Files\\Core" FILES ${INCLUDE_FILES})
|
source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES})
|
||||||
source_group("Source Files\\Third_Party" FILES ${THIRD_PARTY_SOURCE_FILES})
|
|
||||||
|
|
||||||
add_executable(Alber ${SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES})
|
add_executable(Alber ${SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES} ${HEADER_FILES})
|
||||||
target_link_libraries(Alber PRIVATE sfml-system sfml-network sfml-graphics sfml-window dynarmic)
|
target_link_libraries(Alber PRIVATE sfml-system sfml-network sfml-graphics sfml-window dynarmic)
|
9
include/cpu.hpp
Normal file
9
include/cpu.hpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef CPU_DYNARMIC
|
||||||
|
#include "cpu_dynarmic.hpp"
|
||||||
|
#elif defined(CPU_KVM)
|
||||||
|
#error KVM CPU is not implemented yet
|
||||||
|
#else
|
||||||
|
#error No CPU core implemented :(
|
||||||
|
#endif
|
105
include/cpu_dynarmic.hpp
Normal file
105
include/cpu_dynarmic.hpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dynarmic/interface/A32/a32.h"
|
||||||
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
#include "helpers.hpp"
|
||||||
|
|
||||||
|
class MyEnvironment final : public Dynarmic::A32::UserCallbacks {
|
||||||
|
public:
|
||||||
|
u64 ticks_left = 0;
|
||||||
|
std::array<u8, 2048> memory{};
|
||||||
|
|
||||||
|
u8 MemoryRead8(u32 vaddr) override {
|
||||||
|
if (vaddr >= memory.size()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return memory[vaddr];
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 MemoryRead16(u32 vaddr) override {
|
||||||
|
return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 MemoryRead32(u32 vaddr) override {
|
||||||
|
return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 MemoryRead64(u32 vaddr) override {
|
||||||
|
return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryWrite8(u32 vaddr, u8 value) override {
|
||||||
|
if (vaddr >= memory.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memory[vaddr] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryWrite16(u32 vaddr, u16 value) override {
|
||||||
|
MemoryWrite8(vaddr, u8(value));
|
||||||
|
MemoryWrite8(vaddr + 1, u8(value >> 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryWrite32(u32 vaddr, u32 value) override {
|
||||||
|
MemoryWrite16(vaddr, u16(value));
|
||||||
|
MemoryWrite16(vaddr + 2, u16(value >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryWrite64(u32 vaddr, u64 value) override {
|
||||||
|
MemoryWrite32(vaddr, u32(value));
|
||||||
|
MemoryWrite32(vaddr + 4, u32(value >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InterpreterFallback(u32 pc, size_t num_instructions) override {
|
||||||
|
// This is never called in practice.
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallSVC(u32 swi) override {
|
||||||
|
Helpers::panic("Called SVC %d", swi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
|
||||||
|
Helpers::panic("Fired exception oops");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddTicks(u64 ticks) override {
|
||||||
|
if (ticks > ticks_left) {
|
||||||
|
ticks_left = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ticks_left -= ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetTicksRemaining() override {
|
||||||
|
return ticks_left;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPU {
|
||||||
|
MyEnvironment env;
|
||||||
|
Dynarmic::A32::Jit jit{ {.callbacks = &env} };
|
||||||
|
|
||||||
|
public:
|
||||||
|
CPU();
|
||||||
|
|
||||||
|
void setReg(int index, u32 value) {
|
||||||
|
jit.Regs()[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getReg(int index) {
|
||||||
|
return jit.Regs()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<u32, 16>& regs() {
|
||||||
|
return jit.Regs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCPSR(u32 value) {
|
||||||
|
jit.SetCpsr(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getCPSR() {
|
||||||
|
return jit.Cpsr();
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,11 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#define NOMINMAX // Windows why
|
#define NOMINMAX // Windows why
|
||||||
|
#include "cpu.hpp"
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "opengl.hpp"
|
#include "opengl.hpp"
|
||||||
#include "SFML/Window.hpp"
|
#include "SFML/Window.hpp"
|
||||||
#include "SFML/Graphics.hpp"
|
#include "SFML/Graphics.hpp"
|
||||||
|
|
||||||
class Emulator {
|
class Emulator {
|
||||||
|
CPU cpu;
|
||||||
sf::RenderWindow window;
|
sf::RenderWindow window;
|
||||||
static constexpr u32 width = 400;
|
static constexpr u32 width = 400;
|
||||||
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
||||||
|
|
28
src/CPU/cpu_dynarmic.cpp
Normal file
28
src/CPU/cpu_dynarmic.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifdef CPU_DYNARMIC
|
||||||
|
#include "cpu_dynarmic.hpp"
|
||||||
|
|
||||||
|
CPU::CPU() {
|
||||||
|
// Execute at least 1 instruction.
|
||||||
|
// (Note: More than one instruction may be executed.)
|
||||||
|
env.ticks_left = 1;
|
||||||
|
|
||||||
|
// Write some code to memory.
|
||||||
|
env.MemoryWrite16(0, 0x0088); // lsls r0, r1, #2
|
||||||
|
env.MemoryWrite16(2, 0x3045); // adds r0, #69
|
||||||
|
env.MemoryWrite16(4, 0xE7FE); // b +#0 (infinite loop)
|
||||||
|
|
||||||
|
// Setup registers.
|
||||||
|
auto& regs = jit.Regs();
|
||||||
|
regs[0] = 1;
|
||||||
|
regs[1] = 2;
|
||||||
|
regs[15] = 0; // PC = 0
|
||||||
|
setCPSR(0x00000030); // Thumb mode
|
||||||
|
|
||||||
|
// Execute!
|
||||||
|
jit.Run();
|
||||||
|
|
||||||
|
// Here we would expect cpu.Regs()[0] == 77
|
||||||
|
printf("R0: %u\n", jit.Regs()[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CPU_DYNARMIC
|
100
src/main.cpp
100
src/main.cpp
|
@ -1,111 +1,11 @@
|
||||||
#include "dynarmic/interface/A32/a32.h"
|
|
||||||
#include "dynarmic/interface/A32/config.h"
|
|
||||||
#include "emulator.hpp"
|
#include "emulator.hpp"
|
||||||
#include "gl3w.h"
|
#include "gl3w.h"
|
||||||
|
|
||||||
class MyEnvironment final : public Dynarmic::A32::UserCallbacks {
|
|
||||||
public:
|
|
||||||
u64 ticks_left = 0;
|
|
||||||
std::array<u8, 2048> memory{};
|
|
||||||
|
|
||||||
u8 MemoryRead8(u32 vaddr) override {
|
|
||||||
if (vaddr >= memory.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return memory[vaddr];
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 MemoryRead16(u32 vaddr) override {
|
|
||||||
return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 MemoryRead32(u32 vaddr) override {
|
|
||||||
return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 MemoryRead64(u32 vaddr) override {
|
|
||||||
return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryWrite8(u32 vaddr, u8 value) override {
|
|
||||||
if (vaddr >= memory.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memory[vaddr] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryWrite16(u32 vaddr, u16 value) override {
|
|
||||||
MemoryWrite8(vaddr, u8(value));
|
|
||||||
MemoryWrite8(vaddr + 1, u8(value >> 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryWrite32(u32 vaddr, u32 value) override {
|
|
||||||
MemoryWrite16(vaddr, u16(value));
|
|
||||||
MemoryWrite16(vaddr + 2, u16(value >> 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryWrite64(u32 vaddr, u64 value) override {
|
|
||||||
MemoryWrite32(vaddr, u32(value));
|
|
||||||
MemoryWrite32(vaddr + 4, u32(value >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterFallback(u32 pc, size_t num_instructions) override {
|
|
||||||
// This is never called in practice.
|
|
||||||
std::terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallSVC(u32 swi) override {
|
|
||||||
// Do something.
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
|
|
||||||
// Do something.
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddTicks(u64 ticks) override {
|
|
||||||
if (ticks > ticks_left) {
|
|
||||||
ticks_left = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ticks_left -= ticks;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 GetTicksRemaining() override {
|
|
||||||
return ticks_left;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (int argc, char *argv[]) {
|
||||||
Emulator emu;
|
Emulator emu;
|
||||||
if (gl3wInit()) {
|
if (gl3wInit()) {
|
||||||
Helpers::panic("Failed to initialize OpenGL");
|
Helpers::panic("Failed to initialize OpenGL");
|
||||||
}
|
}
|
||||||
|
|
||||||
MyEnvironment env;
|
|
||||||
Dynarmic::A32::UserConfig user_config;
|
|
||||||
user_config.callbacks = &env;
|
|
||||||
Dynarmic::A32::Jit cpu{user_config};
|
|
||||||
|
|
||||||
// Execute at least 1 instruction.
|
|
||||||
// (Note: More than one instruction may be executed.)
|
|
||||||
env.ticks_left = 1;
|
|
||||||
|
|
||||||
// Write some code to memory.
|
|
||||||
env.MemoryWrite16(0, 0x0088); // lsls r0, r1, #2
|
|
||||||
env.MemoryWrite16(2, 0x3045); // adds r0, #69
|
|
||||||
env.MemoryWrite16(4, 0xE7FE); // b +#0 (infinite loop)
|
|
||||||
|
|
||||||
// Setup registers.
|
|
||||||
cpu.Regs()[0] = 1;
|
|
||||||
cpu.Regs()[1] = 2;
|
|
||||||
cpu.Regs()[15] = 0; // PC = 0
|
|
||||||
cpu.SetCpsr(0x00000030); // Thumb mode
|
|
||||||
|
|
||||||
// Execute!
|
|
||||||
cpu.Run();
|
|
||||||
|
|
||||||
// Here we would expect cpu.Regs()[0] == 77
|
|
||||||
printf("R0: %u\n", cpu.Regs()[0]);
|
|
||||||
|
|
||||||
emu.run();
|
emu.run();
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue