From 2057e0c4479b513a447ea311e4af8bdebec66aaa Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Thu, 15 Sep 2022 06:06:46 +0300 Subject: [PATCH] Proper KVM/Dynarmic split --- CMakeLists.txt | 15 ++++-- include/cpu.hpp | 9 ++++ include/cpu_dynarmic.hpp | 105 +++++++++++++++++++++++++++++++++++++++ include/emulator.hpp | 2 + src/CPU/cpu_dynarmic.cpp | 28 +++++++++++ src/main.cpp | 100 ------------------------------------- 6 files changed, 154 insertions(+), 105 deletions(-) create mode 100644 include/cpu.hpp create mode 100644 include/cpu_dynarmic.hpp create mode 100644 src/CPU/cpu_dynarmic.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index eaf66b2a..a83b9734 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,12 +35,16 @@ if(CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x #set(DYNARMIC_NO_BUNDLED_FMT ON) set(DYNARMIC_FRONTENDS "A32" CACHE STRING "") add_subdirectory(third_party/dynarmic) + add_compile_definitions(CPU_DYNARMIC) else() + add_compile_definitions(CPU_KVM) message(FATAL_ERROR "THIS IS NOT x64 WAIT FOR THE KVM IMPLEMENTATION") endif() -set(SOURCE_FILES src/main.cpp src/emulator.cpp) -set(INCLUDE_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp include/opengl.hpp) +set(SOURCE_FILES src/main.cpp src/emulator.cpp src/cpu/cpu_dynarmic.cpp) +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 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 ) +#add_library(Alber ${HEADER_FILES}) +source_group("Header Files\\Core" FILES ${HEADER_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) \ No newline at end of file diff --git a/include/cpu.hpp b/include/cpu.hpp new file mode 100644 index 00000000..14800e19 --- /dev/null +++ b/include/cpu.hpp @@ -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 \ No newline at end of file diff --git a/include/cpu_dynarmic.hpp b/include/cpu_dynarmic.hpp new file mode 100644 index 00000000..554eadbb --- /dev/null +++ b/include/cpu_dynarmic.hpp @@ -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 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& regs() { + return jit.Regs(); + } + + void setCPSR(u32 value) { + jit.SetCpsr(value); + } + + u32 getCPSR() { + return jit.Cpsr(); + } +}; \ No newline at end of file diff --git a/include/emulator.hpp b/include/emulator.hpp index 46e8462e..6d9d7b51 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -1,11 +1,13 @@ #pragma once #define NOMINMAX // Windows why +#include "cpu.hpp" #include "helpers.hpp" #include "opengl.hpp" #include "SFML/Window.hpp" #include "SFML/Graphics.hpp" class Emulator { + CPU cpu; sf::RenderWindow window; static constexpr u32 width = 400; static constexpr u32 height = 240 * 2; // * 2 because 2 screens diff --git a/src/CPU/cpu_dynarmic.cpp b/src/CPU/cpu_dynarmic.cpp new file mode 100644 index 00000000..d921c07a --- /dev/null +++ b/src/CPU/cpu_dynarmic.cpp @@ -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 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0a8de496..a74a0915 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,111 +1,11 @@ -#include "dynarmic/interface/A32/a32.h" -#include "dynarmic/interface/A32/config.h" #include "emulator.hpp" #include "gl3w.h" -class MyEnvironment final : public Dynarmic::A32::UserCallbacks { -public: - u64 ticks_left = 0; - std::array 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[]) { Emulator emu; if (gl3wInit()) { 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(); } \ No newline at end of file