Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement the Just-in-Time recompiler #8

Merged
merged 5 commits into from
Apr 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "external/atom"]
path = external/atom
url = https://github.com/fleroviux/atom
[submodule "external/lunatic"]
path = external/lunatic
url = https://github.com/fleroviux/lunatic
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

A Nintendo DS emulator developed for fun, with performance and multicore CPUs in mind.
A nearly from scratch rewrite of my previous emulator aiming to try new techniques and achieve higher code quality.
However, at the moment not all code has been rewritten yet. But most games and the firmware boot. Notably the JIT is not integrated yet and 3D graphics are promising but work-in-progress.

**This is highly experimental software.**
I am developing this emulator for fun and learning only.
Expand Down
5 changes: 4 additions & 1 deletion external/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
add_subdirectory(atom)
set(LUNATIC_USE_EXTERNAL_FMT ON CACHE BOOL "" FORCE)

add_subdirectory(atom)
add_subdirectory(lunatic)
1 change: 1 addition & 0 deletions external/lunatic
Submodule lunatic added at 88d3f9
Binary file modified resources/hgss.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 21 additions & 10 deletions src/dual/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(SOURCES
src/arm/tablegen/tablegen.cpp
src/arm/arm.cpp
src/arm/interpreter/tablegen/tablegen.cpp
src/arm/interpreter/interpreter_cpu.cpp
src/common/scheduler.cpp
src/nds/arm7/apu.cpp
src/nds/arm7/dma.cpp
Expand Down Expand Up @@ -50,14 +50,14 @@ set(SOURCES
)

set(HEADERS
src/arm/handlers/arithmetic.inl
src/arm/handlers/handler16.inl
src/arm/handlers/handler32.inl
src/arm/handlers/memory.inl
src/arm/tablegen/decoder.hpp
src/arm/tablegen/gen_arm.hpp
src/arm/tablegen/gen_thumb.hpp
src/arm/arm.hpp
src/arm/interpreter/handlers/arithmetic.inl
src/arm/interpreter/handlers/handler16.inl
src/arm/interpreter/handlers/handler32.inl
src/arm/interpreter/handlers/memory.inl
src/arm/interpreter/tablegen/decoder.hpp
src/arm/interpreter/tablegen/gen_arm.hpp
src/arm/interpreter/tablegen/gen_thumb.hpp
src/arm/interpreter/interpreter_cpu.hpp
src/nds/video_unit/gpu/renderer/software/edge.hpp
src/nds/video_unit/gpu/renderer/software/interpolator.hpp
)
Expand Down Expand Up @@ -104,9 +104,20 @@ set(HEADERS_PUBLIC
include/dual/nds/timer.hpp
)

option(DUAL_ENABLE_JIT "Enable Just-In-Time compiler support" ON)

if(DUAL_ENABLE_JIT)
list(APPEND SOURCES src/arm/jit/lunatic_cpu.cpp)
list(APPEND HEADERS src/arm/jit/lunatic_cpu.hpp)
endif()

add_library(dual ${SOURCES} ${HEADERS} ${HEADERS_PUBLIC})

target_link_libraries(dual PUBLIC atom-common atom-logger atom-math)
if(DUAL_ENABLE_JIT)
target_link_libraries(dual PRIVATE lunatic)
target_compile_definitions(dual PUBLIC DUAL_ENABLE_JIT)
endif()

target_include_directories(dual PUBLIC include)
target_include_directories(dual PRIVATE src)
Expand Down
3 changes: 3 additions & 0 deletions src/dual/include/dual/arm/coprocessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

namespace dual::arm {

class CPU;

class Coprocessor {
public:
virtual ~Coprocessor() = default;

virtual void Reset() {}
virtual void SetCPU(CPU* cpu) {}

virtual u32 MRC(int opc1, int cn, int cm, int opc2) = 0;
virtual void MCR(int opc1, int cn, int cm, int opc2, u32 value) = 0;
Expand Down
8 changes: 7 additions & 1 deletion src/dual/include/dual/arm/cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

namespace dual::arm {

struct AttachCPn {
int id;
dual::arm::Coprocessor* coprocessor;
};

class CPU {
public:
enum class Model {
Expand Down Expand Up @@ -72,7 +77,8 @@ namespace dual::arm {
virtual u32 GetExceptionBase() const = 0;
virtual void SetExceptionBase(u32 address) = 0;

virtual void SetCoprocessor(int id, Coprocessor* coprocessor) = 0;
virtual void InvalidateICache() {}
virtual void InvalidateICacheRange(u32 address_lo, u32 address_hi) {}

virtual void SetUnalignedDataAccessEnable(bool enable) = 0;

Expand Down
3 changes: 2 additions & 1 deletion src/dual/include/dual/nds/arm9/cp15.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ namespace dual::nds::arm9 {

class CP15 final : public arm::Coprocessor {
public:
CP15(arm::CPU* cpu, MemoryBus* bus);
explicit CP15(MemoryBus* bus);

void Reset() override;
void SetCPU(arm::CPU* cpu) override;
void DirectBoot();
u32 MRC(int opc1, int cn, int cm, int opc2) override;
void MCR(int opc1, int cn, int cm, int opc2, u32 value) override;
Expand Down
5 changes: 5 additions & 0 deletions src/dual/include/dual/nds/enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ namespace dual::nds {
return (CPU)((int)cpu ^ 1);
}

enum class CPUExecutionEngine {
Interpreter,
JIT
};

} // namespace dual::nds

template<> struct fmt::formatter<dual::nds::CPU> : formatter<std::string_view> {
Expand Down
5 changes: 5 additions & 0 deletions src/dual/include/dual/nds/nds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace dual::nds {
NDS();

void Reset();
void SetCPUExecutionEngine(CPUExecutionEngine cpu_execution_engine);
void Step(int cycles_to_run);
void LoadBootROM9(std::span<u8, 0x8000> data);
void LoadBootROM7(std::span<u8, 0x4000> data);
Expand All @@ -50,6 +51,8 @@ namespace dual::nds {
void SetTouchState(bool pen_down, u8 x, u8 y);

private:
void CreateCPUCores();

Scheduler m_scheduler{};

SystemMemory m_memory{};
Expand Down Expand Up @@ -123,6 +126,8 @@ namespace dual::nds {
std::shared_ptr<ROM> m_rom;

u64 m_step_target{};

CPUExecutionEngine m_cpu_execution_engine{CPUExecutionEngine::Interpreter};
};

} // namespace dual::nds
3 changes: 2 additions & 1 deletion src/dual/include/dual/nds/rom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace dual::nds {
const u32 address_hi = address + size;

if(address_hi > m_size || address_hi < address) {
ATOM_PANIC("out-of-bounds ROM read request: address=0x{:08X}, size={}", address, size);
//ATOM_PANIC("out-of-bounds ROM read request: address=0x{:08X}, size={}", address, size);
return;
}
std::memcpy(destination, &m_data[address], size);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@

#include "arm.hpp"
#include "interpreter_cpu.hpp"

namespace dual::arm {

ARM::ARM(
InterpreterCPU::InterpreterCPU(
Memory& memory,
Scheduler& scheduler,
CycleCounter& cycle_counter,
Model model
Model model,
std::span<const AttachCPn> coprocessor_table
) : m_memory{memory}
, m_scheduler{scheduler}
, m_cycle_counter{cycle_counter}
Expand All @@ -17,10 +18,13 @@ namespace dual::arm {
BuildConditionTable();
Reset();

m_coprocessors.fill(nullptr);
for(auto& attach_cp_n : coprocessor_table) {
m_coprocessors.at(attach_cp_n.id) = attach_cp_n.coprocessor;
attach_cp_n.coprocessor->SetCPU(this);
}
}

void ARM::Reset() {
void InterpreterCPU::Reset() {
constexpr u32 nop = 0xE320F000;

m_state = {};
Expand All @@ -32,7 +36,7 @@ namespace dual::arm {
SetIRQFlag(false);
}

void ARM::Run(int cycles) {
void InterpreterCPU::Run(int cycles) {
if(GetWaitingForIRQ()) {
m_cycle_counter.AddDeviceCycles((uint)cycles);
return;
Expand Down Expand Up @@ -82,7 +86,7 @@ namespace dual::arm {
}
}

void ARM::SignalIRQ() {
void InterpreterCPU::SignalIRQ() {
if(m_state.cpsr.mask_irq) {
return;
}
Expand All @@ -107,19 +111,19 @@ namespace dual::arm {
ReloadPipeline32();
}

void ARM::ReloadPipeline32() {
void InterpreterCPU::ReloadPipeline32() {
m_opcode[0] = ReadWordCode(m_state.r15);
m_opcode[1] = ReadWordCode(m_state.r15 + 4);
m_state.r15 += 8;
}

void ARM::ReloadPipeline16() {
void InterpreterCPU::ReloadPipeline16() {
m_opcode[0] = ReadHalfCode(m_state.r15);
m_opcode[1] = ReadHalfCode(m_state.r15 + 2);
m_state.r15 += 4;
}

void ARM::BuildConditionTable() {
void InterpreterCPU::BuildConditionTable() {
for(int flags = 0; flags < 16; flags++) {
bool n = flags & 8;
bool z = flags & 4;
Expand All @@ -145,7 +149,7 @@ namespace dual::arm {
}
}

auto ARM::GetRegisterBankByMode(Mode mode) -> Bank {
auto InterpreterCPU::GetRegisterBankByMode(Mode mode) -> Bank {
switch(mode) {
case Mode::User: return Bank::None;
case Mode::System: return Bank::None;
Expand All @@ -159,7 +163,7 @@ namespace dual::arm {
ATOM_PANIC("invalid ARM CPU mode: 0x{:02X}", (uint)mode);
}

void ARM::SwitchMode(Mode new_mode) {
void InterpreterCPU::SwitchMode(Mode new_mode) {
auto old_bank = GetRegisterBankByMode((Mode)m_state.cpsr.mode);
auto new_bank = GetRegisterBankByMode(new_mode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
#include <dual/arm/memory.hpp>
#include <dual/common/cycle_counter.hpp>
#include <dual/common/scheduler.hpp>
#include <span>

namespace dual::arm {

class ARM final : public CPU {
class InterpreterCPU final : public CPU {
public:
ARM(
InterpreterCPU(
Memory& memory,
Scheduler& scheduler,
CycleCounter& cycle_counter,
Model model
Model model,
std::span<const AttachCPn> coprocessor_table = {}
);

void Reset() override;
Expand All @@ -30,10 +32,6 @@ namespace dual::arm {
m_exception_base = address;
}

void SetCoprocessor(int id, Coprocessor* coprocessor) override {
m_coprocessors.at(id) = coprocessor;
}

void SetUnalignedDataAccessEnable(bool enable) override {
m_unaligned_data_access_enable = enable;
}
Expand Down Expand Up @@ -111,8 +109,8 @@ namespace dual::arm {

void Run(int cycles) override;

typedef void (ARM::*Handler16)(u16);
typedef void (ARM::*Handler32)(u32);
typedef void (InterpreterCPU::*Handler16)(u16);
typedef void (InterpreterCPU::*Handler32)(u32);

private:
enum class Condition {
Expand Down Expand Up @@ -169,7 +167,7 @@ namespace dual::arm {
Scheduler& m_scheduler;
CycleCounter& m_cycle_counter;
Model m_model;
std::array<Coprocessor*, 16> m_coprocessors;
std::array<Coprocessor*, 16> m_coprocessors{};

bool m_irq_line;
bool m_wait_for_irq = false;
Expand Down
Loading
Loading