From 7258b897785bb03d2ca082e78fcc05294e890c6f Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Sat, 4 Jul 2015 00:21:03 -0700 Subject: [PATCH] removed RuntimeContext struct --- CMakeLists.txt | 2 + .../backend/interpreter/interpreter_backend.h | 4 +- .../backend/interpreter/interpreter_block.cc | 4 +- .../backend/interpreter/interpreter_block.h | 2 +- .../interpreter/interpreter_callbacks.cc | 40 +++++----- src/cpu/backend/x64/x64_block.cc | 4 +- src/cpu/backend/x64/x64_block.h | 2 +- src/cpu/frontend/sh4/sh4_builder.cc | 4 - src/cpu/runtime.cc | 62 ---------------- src/cpu/runtime.h | 23 +----- src/cpu/sh4.cc | 71 +----------------- src/cpu/sh4.h | 73 +------------------ src/cpu/sh4_context.cc | 65 +++++++++++++++++ src/cpu/sh4_context.h | 67 +++++++++++++++++ src/emu/emulator.cc | 41 +++++------ src/emu/emulator.h | 11 +-- src/main.cc | 9 +-- test/test_sh4.cc | 2 +- 18 files changed, 198 insertions(+), 288 deletions(-) create mode 100644 src/cpu/sh4_context.cc create mode 100644 src/cpu/sh4_context.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f9918bf..0e7d4abf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ set(DREAVM_SOURCES src/cpu/ir/pass_runner.cc src/cpu/ir/validate_block_pass.cc src/cpu/sh4.cc + src/cpu/sh4_context.cc src/cpu/runtime.cc src/emu/disc.cc src/emu/emulator.cc @@ -270,6 +271,7 @@ set(DREAVM_TEST_SOURCES src/cpu/ir/pass_runner.cc src/cpu/ir/validate_block_pass.cc src/cpu/sh4.cc + src/cpu/sh4_context.cc src/cpu/runtime.cc src/emu/profiler.cc src/emu/scheduler.cc diff --git a/src/cpu/backend/interpreter/interpreter_backend.h b/src/cpu/backend/interpreter/interpreter_backend.h index e34c89aa..7639c932 100644 --- a/src/cpu/backend/interpreter/interpreter_backend.h +++ b/src/cpu/backend/interpreter/interpreter_backend.h @@ -12,8 +12,8 @@ namespace interpreter { class InterpreterContext; -typedef uint32_t (*InstrFn)(RuntimeContext *runtime, Register *registers, - Instr *instr, uint32_t idx); +typedef uint32_t (*InstrFn)(emu::Memory *memory, void *guest_ctx, + Register *registers, Instr *instr, uint32_t idx); union Register { int8_t i8; diff --git a/src/cpu/backend/interpreter/interpreter_block.cc b/src/cpu/backend/interpreter/interpreter_block.cc index 424c6563..efd37aa1 100644 --- a/src/cpu/backend/interpreter/interpreter_block.cc +++ b/src/cpu/backend/interpreter/interpreter_block.cc @@ -15,7 +15,7 @@ InterpreterBlock::InterpreterBlock(int guest_cycles, Instr *instrs, InterpreterBlock::~InterpreterBlock() { free(instrs_); } -uint32_t InterpreterBlock::Call(RuntimeContext &runtime_ctx) { +uint32_t InterpreterBlock::Call(emu::Memory *memory, void *guest_ctx) { Register *registers = reinterpret_cast(alloca(sizeof(Register) * num_registers_)); @@ -33,7 +33,7 @@ uint32_t InterpreterBlock::Call(RuntimeContext &runtime_ctx) { // 3. branch is a far, direct branch, absolute i32 address is returned // cases 2 or 3 will always occur as the last instruction of the block, // so the return can be assumed to be an i32 address then - i = instr->fn(&runtime_ctx, registers, instr, i); + i = instr->fn(memory, guest_ctx, registers, instr, i); } return i; diff --git a/src/cpu/backend/interpreter/interpreter_block.h b/src/cpu/backend/interpreter/interpreter_block.h index 8e57368e..95575c79 100644 --- a/src/cpu/backend/interpreter/interpreter_block.h +++ b/src/cpu/backend/interpreter/interpreter_block.h @@ -19,7 +19,7 @@ class InterpreterBlock : public RuntimeBlock { int num_registers); ~InterpreterBlock(); - uint32_t Call(RuntimeContext &runtime_ctx); + uint32_t Call(emu::Memory *memory, void *guest_ctx); private: Instr *instrs_; diff --git a/src/cpu/backend/interpreter/interpreter_callbacks.cc b/src/cpu/backend/interpreter/interpreter_callbacks.cc index 0e596a7e..ce8b22ed 100644 --- a/src/cpu/backend/interpreter/interpreter_callbacks.cc +++ b/src/cpu/backend/interpreter/interpreter_callbacks.cc @@ -177,10 +177,10 @@ struct helper \ - static uint32_t name(RuntimeContext *ctx, Register *r, Instr *i, \ +#define CALLBACK(name) \ + template \ + static uint32_t name(Memory *memory, void *guest_ctx, Register *r, Instr *i, \ uint32_t idx) #define LOAD_ARG0() helper::LoadArg(r, i) #define LOAD_ARG1() helper::LoadArg(r, i) @@ -203,8 +203,7 @@ CALLBACK(PRINTF) { CALLBACK(LOAD_CONTEXT) { A0 offset = LOAD_ARG0(); - R v = *reinterpret_cast(reinterpret_cast(ctx->guest_ctx) + - offset); + R v = *reinterpret_cast(reinterpret_cast(guest_ctx) + offset); STORE_RESULT(v); return NEXT_INSTR; } @@ -212,49 +211,48 @@ CALLBACK(LOAD_CONTEXT) { CALLBACK(STORE_CONTEXT) { A0 offset = LOAD_ARG0(); A1 v = LOAD_ARG1(); - *reinterpret_cast(reinterpret_cast(ctx->guest_ctx) + - offset) = v; + *reinterpret_cast(reinterpret_cast(guest_ctx) + offset) = v; return NEXT_INSTR; } CALLBACK(LOAD_I8) { uint32_t addr = (uint32_t)LOAD_ARG0(); - R v = ctx->R8(ctx, addr); + R v = memory->R8(addr); STORE_RESULT(v); return NEXT_INSTR; } CALLBACK(LOAD_I16) { uint32_t addr = (uint32_t)LOAD_ARG0(); - R v = ctx->R16(ctx, addr); + R v = memory->R16(addr); STORE_RESULT(v); return NEXT_INSTR; } CALLBACK(LOAD_I32) { uint32_t addr = (uint32_t)LOAD_ARG0(); - R v = ctx->R32(ctx, addr); + R v = memory->R32(addr); STORE_RESULT(v); return NEXT_INSTR; } CALLBACK(LOAD_I64) { uint32_t addr = (uint32_t)LOAD_ARG0(); - R v = ctx->R64(ctx, addr); + R v = memory->R64(addr); STORE_RESULT(v); return NEXT_INSTR; } CALLBACK(LOAD_F32) { uint32_t addr = (uint32_t)LOAD_ARG0(); - R v = ctx->RF32(ctx, addr); + R v = memory->RF32(addr); STORE_RESULT(v); return NEXT_INSTR; } CALLBACK(LOAD_F64) { uint32_t addr = (uint32_t)LOAD_ARG0(); - R v = ctx->RF64(ctx, addr); + R v = memory->RF64(addr); STORE_RESULT(v); return NEXT_INSTR; } @@ -348,42 +346,42 @@ CALLBACK(LOAD_DYN_F64) { CALLBACK(STORE_I8) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); - ctx->W8(ctx, addr, v); + memory->W8(addr, v); return NEXT_INSTR; } CALLBACK(STORE_I16) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); - ctx->W16(ctx, addr, v); + memory->W16(addr, v); return NEXT_INSTR; } CALLBACK(STORE_I32) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); - ctx->W32(ctx, addr, v); + memory->W32(addr, v); return NEXT_INSTR; } CALLBACK(STORE_I64) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); - ctx->W64(ctx, addr, v); + memory->W64(addr, v); return NEXT_INSTR; } CALLBACK(STORE_F32) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); - ctx->WF32(ctx, addr, v); + memory->WF32(addr, v); return NEXT_INSTR; } CALLBACK(STORE_F64) { uint32_t addr = (uint32_t)LOAD_ARG0(); A1 v = LOAD_ARG1(); - ctx->WF64(ctx, addr, v); + memory->WF64(addr, v); return NEXT_INSTR; } @@ -757,7 +755,7 @@ CALLBACK(BRANCH_INDIRECT) { CALLBACK(CALL_EXTERNAL) { A0 addr = LOAD_ARG0(); void (*func)(void *) = (void (*)(void *))(intptr_t)addr; - func(ctx->guest_ctx); + func(guest_ctx); return NEXT_INSTR; } diff --git a/src/cpu/backend/x64/x64_block.cc b/src/cpu/backend/x64/x64_block.cc index 5eb7836a..0004e24d 100644 --- a/src/cpu/backend/x64/x64_block.cc +++ b/src/cpu/backend/x64/x64_block.cc @@ -10,4 +10,6 @@ X64Block::X64Block(int guest_cycles) : RuntimeBlock(guest_cycles) {} X64Block::~X64Block() {} -uint32_t X64Block::Call(RuntimeContext &runtime_ctx) { return 0xdeadbeef; } +uint32_t X64Block::Call(emu::Memory *memory, void *guest_ctx) { + return 0xdeadbeef; +} diff --git a/src/cpu/backend/x64/x64_block.h b/src/cpu/backend/x64/x64_block.h index 634fc30d..c418a8bb 100644 --- a/src/cpu/backend/x64/x64_block.h +++ b/src/cpu/backend/x64/x64_block.h @@ -15,7 +15,7 @@ class X64Block : public RuntimeBlock { X64Block(int guest_cycles); ~X64Block(); - uint32_t Call(RuntimeContext &runtime_ctx); + uint32_t Call(emu::Memory *memory, void *guest_ctx); private: }; diff --git a/src/cpu/frontend/sh4/sh4_builder.cc b/src/cpu/frontend/sh4/sh4_builder.cc index 85de5107..1690b9a0 100644 --- a/src/cpu/frontend/sh4/sh4_builder.cc +++ b/src/cpu/frontend/sh4/sh4_builder.cc @@ -9,10 +9,6 @@ using namespace dreavm::cpu::frontend::sh4; using namespace dreavm::cpu::ir; using namespace dreavm::emu; -void SRUpdated(SH4Context *ctx) { ctx->SRUpdated(); } - -void FPSCRUpdated(SH4Context *ctx) { ctx->FPSCRUpdated(); } - SH4Builder::SH4Builder(Memory &memory) : memory_(memory), has_delay_instr_(false), last_instr_(nullptr) {} diff --git a/src/cpu/runtime.cc b/src/cpu/runtime.cc index e5c71884..d18bcc71 100644 --- a/src/cpu/runtime.cc +++ b/src/cpu/runtime.cc @@ -13,54 +13,6 @@ using namespace dreavm::cpu; using namespace dreavm::cpu::ir; using namespace dreavm::emu; -static uint8_t R8(RuntimeContext *ctx, uint32_t addr) { - return ctx->runtime->memory().R8(addr); -} - -static uint16_t R16(RuntimeContext *ctx, uint32_t addr) { - return ctx->runtime->memory().R16(addr); -} - -static uint32_t R32(RuntimeContext *ctx, uint32_t addr) { - return ctx->runtime->memory().R32(addr); -} - -static uint64_t R64(RuntimeContext *ctx, uint32_t addr) { - return ctx->runtime->memory().R64(addr); -} - -static float RF32(RuntimeContext *ctx, uint32_t addr) { - return ctx->runtime->memory().RF32(addr); -} - -static double RF64(RuntimeContext *ctx, uint32_t addr) { - return ctx->runtime->memory().RF64(addr); -} - -static void W8(RuntimeContext *ctx, uint32_t addr, uint8_t value) { - ctx->runtime->memory().W8(addr, value); -} - -static void W16(RuntimeContext *ctx, uint32_t addr, uint16_t value) { - ctx->runtime->memory().W16(addr, value); -} - -static void W32(RuntimeContext *ctx, uint32_t addr, uint32_t value) { - ctx->runtime->memory().W32(addr, value); -} - -static void W64(RuntimeContext *ctx, uint32_t addr, uint64_t value) { - ctx->runtime->memory().W64(addr, value); -} - -static void WF32(RuntimeContext *ctx, uint32_t addr, float value) { - ctx->runtime->memory().WF32(addr, value); -} - -static void WF64(RuntimeContext *ctx, uint32_t addr, double value) { - ctx->runtime->memory().WF64(addr, value); -} - Runtime::Runtime(Memory &memory) : memory_(memory), frontend_(nullptr), @@ -68,20 +20,6 @@ Runtime::Runtime(Memory &memory) pending_reset_(false) { blocks_ = new std::unique_ptr[MAX_BLOCKS]; - runtime_ctx_.runtime = this; - runtime_ctx_.R8 = &::R8; - runtime_ctx_.R16 = &::R16; - runtime_ctx_.R32 = &::R32; - runtime_ctx_.R64 = &::R64; - runtime_ctx_.RF32 = &::RF32; - runtime_ctx_.RF64 = &::RF64; - runtime_ctx_.W8 = &::W8; - runtime_ctx_.W16 = &::W16; - runtime_ctx_.W32 = &::W32; - runtime_ctx_.W64 = &::W64; - runtime_ctx_.WF32 = &::WF32; - runtime_ctx_.WF64 = &::WF64; - pass_runner_.AddPass(std::unique_ptr(new ValidateBlockPass())); pass_runner_.AddPass(std::unique_ptr(new ControlFlowAnalysisPass())); pass_runner_.AddPass(std::unique_ptr(new ContextPromotionPass())); diff --git a/src/cpu/runtime.h b/src/cpu/runtime.h index 43bd354f..1e9c866c 100644 --- a/src/cpu/runtime.h +++ b/src/cpu/runtime.h @@ -31,25 +31,6 @@ static inline uint32_t BlockOffset(uint32_t addr) { class Runtime; class RuntimeBlock; -struct RuntimeContext { - RuntimeContext() : runtime(nullptr), guest_ctx(nullptr) {} - - Runtime *runtime; - void *guest_ctx; - uint8_t (*R8)(RuntimeContext *, uint32_t); - uint16_t (*R16)(RuntimeContext *, uint32_t); - uint32_t (*R32)(RuntimeContext *, uint32_t); - uint64_t (*R64)(RuntimeContext *, uint32_t); - float (*RF32)(RuntimeContext *, uint32_t); - double (*RF64)(RuntimeContext *, uint32_t); - void (*W8)(RuntimeContext *, uint32_t, uint8_t); - void (*W16)(RuntimeContext *, uint32_t, uint16_t); - void (*W32)(RuntimeContext *, uint32_t, uint32_t); - void (*W64)(RuntimeContext *, uint32_t, uint64_t); - void (*WF32)(RuntimeContext *, uint32_t, float); - void (*WF64)(RuntimeContext *, uint32_t, double); -}; - class RuntimeBlock { public: RuntimeBlock(int guest_cycles) : guest_cycles_(guest_cycles) {} @@ -57,7 +38,7 @@ class RuntimeBlock { int guest_cycles() { return guest_cycles_; } - virtual uint32_t Call(RuntimeContext &runtime_ctx) = 0; + virtual uint32_t Call(emu::Memory *memory, void *guest_ctx) = 0; private: int guest_cycles_; @@ -69,7 +50,6 @@ class Runtime { ~Runtime(); emu::Memory &memory() { return memory_; } - RuntimeContext &ctx() { return runtime_ctx_; } bool Init(frontend::Frontend *frontend, backend::Backend *backend); RuntimeBlock *ResolveBlock(uint32_t addr); @@ -82,7 +62,6 @@ class Runtime { emu::Memory &memory_; frontend::Frontend *frontend_; backend::Backend *backend_; - RuntimeContext runtime_ctx_; ir::PassRunner pass_runner_; // FIXME 64 mb, could cut down to 8 mb if indices were stored instead of // pointers diff --git a/src/cpu/sh4.cc b/src/cpu/sh4.cc index 0acf3035..2a38e244 100644 --- a/src/cpu/sh4.cc +++ b/src/cpu/sh4.cc @@ -14,63 +14,6 @@ InterruptInfo interrupts[NUM_INTERRUPTS] = { #undef SH4_INT }; -void SH4Context::SetRegisterBank(int bank) { - if (bank == 0) { - for (int s = 0; s < 8; s++) { - rbnk[1][s] = r[s]; - r[s] = rbnk[0][s]; - } - } else { - for (int s = 0; s < 8; s++) { - rbnk[0][s] = r[s]; - r[s] = rbnk[1][s]; - } - } -} - -void SH4Context::SwapFPRegisters() { - unsigned s; - uint32_t z; - - for (s = 0; s <= 15; s++) { - z = fr[s]; - fr[s] = xf[s]; - xf[s] = z; - } -} - -void SH4Context::SwapFPCouples() { - int s; - uint32_t z; - - for (s = 0; s <= 15; s = s + 2) { - z = fr[s]; - fr[s] = fr[s + 1]; - fr[s + 1] = z; - z = xf[s]; - xf[s] = xf[s + 1]; - xf[s + 1] = z; - } -} - -void SH4Context::SRUpdated() { - if (sr.RB != old_sr.RB) { - SetRegisterBank(sr.RB ? 1 : 0); - } - old_sr = sr; - sh4->UpdatePendingInterrupts(); -} - -void SH4Context::FPSCRUpdated() { - if (fpscr.FR != old_fpscr.FR) { - SwapFPRegisters(); - } - if (fpscr.PR != old_fpscr.PR) { - SwapFPCouples(); - } - old_fpscr = fpscr; -} - SH4::SH4(emu::Scheduler &scheduler, Memory &memory) : scheduler_(scheduler), memory_(memory) {} @@ -78,9 +21,6 @@ SH4::~SH4() {} bool SH4::Init(Runtime *runtime) { runtime_ = runtime; - if (runtime_) { - runtime_->ctx().guest_ctx = &ctx_; - } scheduler_.AddDevice(this); @@ -108,7 +48,7 @@ int64_t SH4::Execute(int64_t cycles) { RuntimeBlock *block = runtime_->ResolveBlock(ctx_.pc); CHECK(block); - uint32_t nextpc = block->Call(runtime_->ctx()); + uint32_t nextpc = block->Call(&memory_, &ctx_); remaining -= block->guest_cycles(); ctx_.pc = nextpc; @@ -316,8 +256,8 @@ void SH4::InitMemory() { void SH4::InitContext() { memset(&ctx_, 0, sizeof(ctx_)); ctx_.sh4 = this; - // ctx_.pc = 0xa0000000; - ctx_.pc = 0x0c010000; + ctx_.pc = 0xa0000000; + // ctx_.pc = 0x0c010000; ctx_.pr = 0xdeadbeef; #define SH4_REG(addr, name, flags, default, reset, sleep, standby, type) \ if (default != HELD) { \ @@ -399,10 +339,7 @@ void SH4::CheckPendingInterrupts() { ctx_.sr.BL = 1; ctx_.sr.MD = 1; ctx_.sr.RB = 1; - if (ctx_.old_sr.RB != ctx_.sr.RB) { - ctx_.SetRegisterBank(1); - } - ctx_.old_sr = ctx_.sr; + SRUpdated(&ctx_); ctx_.pc = ctx_.vbr + 0x600; if (ctx_.sleep_mode == 1) { ctx_.sleep_mode = 2; diff --git a/src/cpu/sh4.h b/src/cpu/sh4.h index c4174a5e..d2d37677 100644 --- a/src/cpu/sh4.h +++ b/src/cpu/sh4.h @@ -1,6 +1,7 @@ #ifndef SH4_H #define SH4_H +#include "cpu/sh4_context.h" #include "emu/device.h" #include "emu/memory.h" #include "emu/scheduler.h" @@ -12,8 +13,6 @@ namespace cpu { class Runtime; -enum { MAX_FRAMES = 4096 }; - // registers enum { UNDEFINED = 0x0, @@ -48,40 +47,6 @@ union CCR_T { uint32_t full; }; -union SR_T { - struct { - uint32_t T : 1; - uint32_t S : 1; - uint32_t reserved : 2; - uint32_t IMASK : 4; - uint32_t Q : 1; - uint32_t M : 1; - uint32_t reserved1 : 5; - uint32_t FD : 1; - uint32_t reserved2 : 12; - uint32_t BL : 1; - uint32_t RB : 1; - uint32_t MD : 1; - uint32_t reserved3 : 1; - }; - uint32_t full; -}; - -union FPSCR_T { - struct { - uint32_t RM : 2; - uint32_t flag : 5; - uint32_t enable : 5; - uint32_t cause : 6; - uint32_t DN : 1; - uint32_t PR : 1; - uint32_t SZ : 1; - uint32_t FR : 1; - uint32_t reserved : 10; - }; - uint32_t full; -}; - union CHCR_T { struct { uint32_t DE : 1; @@ -140,40 +105,8 @@ enum DDTRW { // DDT_W }; -// SH4 state is split into the SH4Context class for the JIT to easily access -class SH4; - -class SH4Context { - public: - void SetRegisterBank(int bank); - void SwapFPRegisters(); - void SwapFPCouples(); - - void SRUpdated(); - void FPSCRUpdated(); - - SH4 *sh4; - uint32_t pc, spc; - uint32_t pr; - uint32_t gbr, vbr; - uint32_t mach, macl; - uint32_t r[16], rbnk[2][8], sgr; - uint32_t fr[16], xf[16]; - uint32_t fpul; - uint32_t dbr; - uint32_t m[0x4000]; - uint32_t sq[2][8]; - uint8_t sleep_mode; - - uint32_t ea; - int64_t icount, nextcheck; - - SR_T sr, ssr, old_sr; - FPSCR_T fpscr, old_fpscr; -}; - class SH4 : public emu::Device { - friend class SH4Context; + friend void SRUpdated(SH4Context *ctx); friend void RunSH4Test(const SH4Test &); public: @@ -205,10 +138,10 @@ class SH4 : public emu::Device { void InitMemory(); void InitContext(); - SH4Context ctx_; emu::Scheduler &scheduler_; emu::Memory &memory_; Runtime *runtime_; + SH4Context ctx_; #define SH4_REG(addr, name, flags, default, reset, sleep, standby, type) \ type &name{reinterpret_cast(ctx_.m[name##_OFFSET])}; #include "cpu/sh4_regs.inc" diff --git a/src/cpu/sh4_context.cc b/src/cpu/sh4_context.cc new file mode 100644 index 00000000..a94fa457 --- /dev/null +++ b/src/cpu/sh4_context.cc @@ -0,0 +1,65 @@ +#include "core/core.h" +#include "cpu/sh4.h" +#include "cpu/sh4_context.h" + +namespace dreavm { +namespace cpu { + +static void SetRegisterBank(SH4Context *ctx, int bank) { + if (bank == 0) { + for (int s = 0; s < 8; s++) { + ctx->rbnk[1][s] = ctx->r[s]; + ctx->r[s] = ctx->rbnk[0][s]; + } + } else { + for (int s = 0; s < 8; s++) { + ctx->rbnk[0][s] = ctx->r[s]; + ctx->r[s] = ctx->rbnk[1][s]; + } + } +} + +static void SwapFPRegisters(SH4Context *ctx) { + unsigned s; + uint32_t z; + + for (s = 0; s <= 15; s++) { + z = ctx->fr[s]; + ctx->fr[s] = ctx->xf[s]; + ctx->xf[s] = z; + } +} + +static void SwapFPCouples(SH4Context *ctx) { + int s; + uint32_t z; + + for (s = 0; s <= 15; s = s + 2) { + z = ctx->fr[s]; + ctx->fr[s] = ctx->fr[s + 1]; + ctx->fr[s + 1] = z; + z = ctx->xf[s]; + ctx->xf[s] = ctx->xf[s + 1]; + ctx->xf[s + 1] = z; + } +} + +void SRUpdated(SH4Context *ctx) { + if (ctx->sr.RB != ctx->old_sr.RB) { + SetRegisterBank(ctx, ctx->sr.RB ? 1 : 0); + } + ctx->sh4->UpdatePendingInterrupts(); + ctx->old_sr = ctx->sr; +} + +void FPSCRUpdated(SH4Context *ctx) { + if (ctx->fpscr.FR != ctx->old_fpscr.FR) { + SwapFPRegisters(ctx); + } + if (ctx->fpscr.PR != ctx->old_fpscr.PR) { + SwapFPCouples(ctx); + } + ctx->old_fpscr = ctx->fpscr; +} +} +} diff --git a/src/cpu/sh4_context.h b/src/cpu/sh4_context.h new file mode 100644 index 00000000..8463260e --- /dev/null +++ b/src/cpu/sh4_context.h @@ -0,0 +1,67 @@ +#ifndef SH4_CONTEXT_H +#define SH4_CONTEXT_H + +#include + +namespace dreavm { +namespace cpu { + +union SR_T { + struct { + uint32_t T : 1; + uint32_t S : 1; + uint32_t reserved : 2; + uint32_t IMASK : 4; + uint32_t Q : 1; + uint32_t M : 1; + uint32_t reserved1 : 5; + uint32_t FD : 1; + uint32_t reserved2 : 12; + uint32_t BL : 1; + uint32_t RB : 1; + uint32_t MD : 1; + uint32_t reserved3 : 1; + }; + uint32_t full; +}; + +union FPSCR_T { + struct { + uint32_t RM : 2; + uint32_t flag : 5; + uint32_t enable : 5; + uint32_t cause : 6; + uint32_t DN : 1; + uint32_t PR : 1; + uint32_t SZ : 1; + uint32_t FR : 1; + uint32_t reserved : 10; + }; + uint32_t full; +}; + +class SH4; + +struct SH4Context { + SH4 *sh4; + uint32_t pc, spc; + uint32_t pr; + uint32_t gbr, vbr; + uint32_t mach, macl; + uint32_t r[16], rbnk[2][8], sgr; + uint32_t fr[16], xf[16]; + uint32_t fpul; + uint32_t dbr; + uint32_t m[0x4000]; + uint32_t sq[2][8]; + uint8_t sleep_mode; + SR_T sr, ssr, old_sr; + FPSCR_T fpscr, old_fpscr; +}; + +void SRUpdated(SH4Context *ctx); +void FPSCRUpdated(SH4Context *ctx); +} +} + +#endif diff --git a/src/emu/emulator.cc b/src/emu/emulator.cc index 5db048e6..e0468fc8 100644 --- a/src/emu/emulator.cc +++ b/src/emu/emulator.cc @@ -20,27 +20,20 @@ using namespace dreavm::system; Emulator::Emulator(System &sys) : sys_(sys), - scheduler_(new Scheduler()), - memory_(new Memory()), - rt_frontend_(new SH4Frontend(*memory_)), - rt_backend_(new InterpreterBackend(*memory_)), - // rt_backend_(new X64Backend(*memory_)), - runtime_(new Runtime(*memory_)), - processor_(new SH4(*scheduler_, *memory_)), - holly_(new Holly(*scheduler_, *memory_, *processor_)) { + runtime_(memory_), + processor_(scheduler_, memory_), + holly_(scheduler_, memory_, processor_) { + rt_frontend_ = new SH4Frontend(memory_); + rt_backend_ = new InterpreterBackend(memory_); + // rt_backend_ = new X64Backend(*memory_); rb_ = new GLBackend(sys); } Emulator::~Emulator() { Profiler::Shutdown(); delete rb_; - delete holly_; - delete processor_; - delete runtime_; delete rt_backend_; delete rt_frontend_; - delete memory_; - delete scheduler_; } bool Emulator::Init() { @@ -64,17 +57,17 @@ bool Emulator::Init() { return false; } - if (!runtime_->Init(rt_frontend_, rt_backend_)) { + if (!runtime_.Init(rt_frontend_, rt_backend_)) { return false; } // order here is important, sh4 memory handlers need to override // some of the broader holly handlers - if (!holly_->Init(rb_)) { + if (!holly_.Init(rb_)) { return false; } - if (!processor_->Init(runtime_)) { + if (!processor_.Init(&runtime_)) { return false; } @@ -102,7 +95,7 @@ bool Emulator::LaunchBIN(const char *path) { // load to 0x0c010000 (area 3) which is where 1ST_READ.BIN is normally // loaded to - memory_->Memcpy(0x0c010000, data, size); + memory_.Memcpy(0x0c010000, data, size); free(data); return true; } @@ -114,7 +107,7 @@ bool Emulator::LaunchGDI(const char *path) { return false; } - holly_->gdrom().SetDisc(std::move(gdi)); + holly_.gdrom().SetDisc(std::move(gdi)); return true; } @@ -122,14 +115,14 @@ bool Emulator::LaunchGDI(const char *path) { void Emulator::Tick() { PumpEvents(); - scheduler_->Tick(); + scheduler_.Tick(); RenderFrame(); } // for memory mapping notes, see 2.1 System Mapping in the hardware manual bool Emulator::MountRam() { - memory_->Alloc(0x0, 0x1fffffff, 0xe0000000); + memory_.Alloc(0x0, 0x1fffffff, 0xe0000000); return true; } @@ -164,7 +157,7 @@ bool Emulator::LoadBios(const char *path) { return false; } - memory_->Memcpy(BIOS_START, data, size); + memory_.Memcpy(BIOS_START, data, size); free(data); return true; } @@ -200,7 +193,7 @@ bool Emulator::LoadFlash(const char *path) { return false; } - memory_->Memcpy(FLASH_START, data, size); + memory_.Memcpy(FLASH_START, data, size); free(data); return true; } @@ -212,7 +205,7 @@ void Emulator::PumpEvents() { // let the profiler take a stab at the input first if (!Profiler::HandleInput(ev.key.code, ev.key.value)) { // else, forward to holly - holly_->HandleInput(0, ev.key.code, ev.key.value); + holly_.HandleInput(0, ev.key.code, ev.key.value); } } else if (ev.type == SE_MOUSEMOVE) { Profiler::HandleMouseMove(ev.mousemove.x, ev.mousemove.y); @@ -231,7 +224,7 @@ void Emulator::RenderFrame() { // render stats char stats[512]; snprintf(stats, sizeof(stats), "%.2f%%, %.2f fps, %.2f vbps", - scheduler_->perf(), holly_->fps(), holly_->vbps()); + scheduler_.perf(), holly_.fps(), holly_.vbps()); LOG_EVERY_N(INFO, 10) << stats; rb_->RenderText2D(0.0f, 0.0f, 12, 0xffffffff, stats); diff --git a/src/emu/emulator.h b/src/emu/emulator.h index 7abe83cb..dd00918f 100644 --- a/src/emu/emulator.h +++ b/src/emu/emulator.h @@ -4,6 +4,7 @@ #include "cpu/sh4.h" #include "cpu/backend/backend.h" #include "cpu/frontend/frontend.h" +#include "cpu/runtime.h" #include "holly/holly.h" #include "holly/maple_controller.h" #include "renderer/backend.h" @@ -31,13 +32,13 @@ class Emulator { void RenderFrame(); system::System &sys_; - emu::Scheduler *scheduler_; - emu::Memory *memory_; + emu::Scheduler scheduler_; + emu::Memory memory_; + cpu::Runtime runtime_; + cpu::SH4 processor_; + holly::Holly holly_; cpu::frontend::Frontend *rt_frontend_; cpu::backend::Backend *rt_backend_; - cpu::Runtime *runtime_; - cpu::SH4 *processor_; - holly::Holly *holly_; renderer::Backend *rb_; }; } diff --git a/src/main.cc b/src/main.cc index f398f5c8..266beb60 100644 --- a/src/main.cc +++ b/src/main.cc @@ -45,11 +45,10 @@ int main(int argc, char **argv) { LOG(FATAL) << "Failed to load bin."; } - // if (!emu.LaunchGDI( - // "../dreamcast/Crazy Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!]/Crazy " - // "Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!].gdi")) { - // LOG(FATAL) << "Failed to load GDI."; - // } + if (!emu.LaunchGDI( + "../dreamcast/Crazy Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!]/Crazy Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!].gdi")) { + LOG(FATAL) << "Failed to load GDI."; + } while (1) { sys.Tick(); diff --git a/test/test_sh4.cc b/test/test_sh4.cc index 2c441818..cd35bf08 100644 --- a/test/test_sh4.cc +++ b/test/test_sh4.cc @@ -20,7 +20,6 @@ namespace cpu { void RunSH4Test(const SH4Test &test) { Scheduler scheduler; Memory memory; - SH4 sh4(scheduler, memory); // initialize runtime frontend::sh4::SH4Frontend sh4_frontend(memory); @@ -29,6 +28,7 @@ void RunSH4Test(const SH4Test &test) { ASSERT_TRUE(runtime.Init(&sh4_frontend, &int_backend)); // initialize device + SH4 sh4(scheduler, memory); ASSERT_TRUE(sh4.Init(&runtime)); // mount the test binary and a small stack