mirror of https://github.com/inolen/redream.git
removed RuntimeContext struct
This commit is contained in:
parent
c4b78cc565
commit
7258b89778
|
@ -63,6 +63,7 @@ set(DREAVM_SOURCES
|
||||||
src/cpu/ir/pass_runner.cc
|
src/cpu/ir/pass_runner.cc
|
||||||
src/cpu/ir/validate_block_pass.cc
|
src/cpu/ir/validate_block_pass.cc
|
||||||
src/cpu/sh4.cc
|
src/cpu/sh4.cc
|
||||||
|
src/cpu/sh4_context.cc
|
||||||
src/cpu/runtime.cc
|
src/cpu/runtime.cc
|
||||||
src/emu/disc.cc
|
src/emu/disc.cc
|
||||||
src/emu/emulator.cc
|
src/emu/emulator.cc
|
||||||
|
@ -270,6 +271,7 @@ set(DREAVM_TEST_SOURCES
|
||||||
src/cpu/ir/pass_runner.cc
|
src/cpu/ir/pass_runner.cc
|
||||||
src/cpu/ir/validate_block_pass.cc
|
src/cpu/ir/validate_block_pass.cc
|
||||||
src/cpu/sh4.cc
|
src/cpu/sh4.cc
|
||||||
|
src/cpu/sh4_context.cc
|
||||||
src/cpu/runtime.cc
|
src/cpu/runtime.cc
|
||||||
src/emu/profiler.cc
|
src/emu/profiler.cc
|
||||||
src/emu/scheduler.cc
|
src/emu/scheduler.cc
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace interpreter {
|
||||||
|
|
||||||
class InterpreterContext;
|
class InterpreterContext;
|
||||||
|
|
||||||
typedef uint32_t (*InstrFn)(RuntimeContext *runtime, Register *registers,
|
typedef uint32_t (*InstrFn)(emu::Memory *memory, void *guest_ctx,
|
||||||
Instr *instr, uint32_t idx);
|
Register *registers, Instr *instr, uint32_t idx);
|
||||||
|
|
||||||
union Register {
|
union Register {
|
||||||
int8_t i8;
|
int8_t i8;
|
||||||
|
|
|
@ -15,7 +15,7 @@ InterpreterBlock::InterpreterBlock(int guest_cycles, Instr *instrs,
|
||||||
|
|
||||||
InterpreterBlock::~InterpreterBlock() { free(instrs_); }
|
InterpreterBlock::~InterpreterBlock() { free(instrs_); }
|
||||||
|
|
||||||
uint32_t InterpreterBlock::Call(RuntimeContext &runtime_ctx) {
|
uint32_t InterpreterBlock::Call(emu::Memory *memory, void *guest_ctx) {
|
||||||
Register *registers =
|
Register *registers =
|
||||||
reinterpret_cast<Register *>(alloca(sizeof(Register) * num_registers_));
|
reinterpret_cast<Register *>(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
|
// 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,
|
// 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
|
// 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;
|
return i;
|
||||||
|
|
|
@ -19,7 +19,7 @@ class InterpreterBlock : public RuntimeBlock {
|
||||||
int num_registers);
|
int num_registers);
|
||||||
~InterpreterBlock();
|
~InterpreterBlock();
|
||||||
|
|
||||||
uint32_t Call(RuntimeContext &runtime_ctx);
|
uint32_t Call(emu::Memory *memory, void *guest_ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Instr *instrs_;
|
Instr *instrs_;
|
||||||
|
|
|
@ -180,7 +180,7 @@ struct helper<T, ARG, IMM_MASK,
|
||||||
#define CALLBACK(name) \
|
#define CALLBACK(name) \
|
||||||
template <typename R = void, typename A0 = void, typename A1 = void, \
|
template <typename R = void, typename A0 = void, typename A1 = void, \
|
||||||
int IMM_MASK = 0> \
|
int IMM_MASK = 0> \
|
||||||
static uint32_t name(RuntimeContext *ctx, Register *r, Instr *i, \
|
static uint32_t name(Memory *memory, void *guest_ctx, Register *r, Instr *i, \
|
||||||
uint32_t idx)
|
uint32_t idx)
|
||||||
#define LOAD_ARG0() helper<A0, 0, IMM_MASK>::LoadArg(r, i)
|
#define LOAD_ARG0() helper<A0, 0, IMM_MASK>::LoadArg(r, i)
|
||||||
#define LOAD_ARG1() helper<A1, 1, IMM_MASK>::LoadArg(r, i)
|
#define LOAD_ARG1() helper<A1, 1, IMM_MASK>::LoadArg(r, i)
|
||||||
|
@ -203,8 +203,7 @@ CALLBACK(PRINTF) {
|
||||||
|
|
||||||
CALLBACK(LOAD_CONTEXT) {
|
CALLBACK(LOAD_CONTEXT) {
|
||||||
A0 offset = LOAD_ARG0();
|
A0 offset = LOAD_ARG0();
|
||||||
R v = *reinterpret_cast<R *>(reinterpret_cast<uint8_t *>(ctx->guest_ctx) +
|
R v = *reinterpret_cast<R *>(reinterpret_cast<uint8_t *>(guest_ctx) + offset);
|
||||||
offset);
|
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
@ -212,49 +211,48 @@ CALLBACK(LOAD_CONTEXT) {
|
||||||
CALLBACK(STORE_CONTEXT) {
|
CALLBACK(STORE_CONTEXT) {
|
||||||
A0 offset = LOAD_ARG0();
|
A0 offset = LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
*reinterpret_cast<A1 *>(reinterpret_cast<uint8_t *>(ctx->guest_ctx) +
|
*reinterpret_cast<A1 *>(reinterpret_cast<uint8_t *>(guest_ctx) + offset) = v;
|
||||||
offset) = v;
|
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(LOAD_I8) {
|
CALLBACK(LOAD_I8) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
R v = ctx->R8(ctx, addr);
|
R v = memory->R8(addr);
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(LOAD_I16) {
|
CALLBACK(LOAD_I16) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
R v = ctx->R16(ctx, addr);
|
R v = memory->R16(addr);
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(LOAD_I32) {
|
CALLBACK(LOAD_I32) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
R v = ctx->R32(ctx, addr);
|
R v = memory->R32(addr);
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(LOAD_I64) {
|
CALLBACK(LOAD_I64) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
R v = ctx->R64(ctx, addr);
|
R v = memory->R64(addr);
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(LOAD_F32) {
|
CALLBACK(LOAD_F32) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
R v = ctx->RF32(ctx, addr);
|
R v = memory->RF32(addr);
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(LOAD_F64) {
|
CALLBACK(LOAD_F64) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
R v = ctx->RF64(ctx, addr);
|
R v = memory->RF64(addr);
|
||||||
STORE_RESULT(v);
|
STORE_RESULT(v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
@ -348,42 +346,42 @@ CALLBACK(LOAD_DYN_F64) {
|
||||||
CALLBACK(STORE_I8) {
|
CALLBACK(STORE_I8) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
ctx->W8(ctx, addr, v);
|
memory->W8(addr, v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(STORE_I16) {
|
CALLBACK(STORE_I16) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
ctx->W16(ctx, addr, v);
|
memory->W16(addr, v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(STORE_I32) {
|
CALLBACK(STORE_I32) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
ctx->W32(ctx, addr, v);
|
memory->W32(addr, v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(STORE_I64) {
|
CALLBACK(STORE_I64) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
ctx->W64(ctx, addr, v);
|
memory->W64(addr, v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(STORE_F32) {
|
CALLBACK(STORE_F32) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
ctx->WF32(ctx, addr, v);
|
memory->WF32(addr, v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(STORE_F64) {
|
CALLBACK(STORE_F64) {
|
||||||
uint32_t addr = (uint32_t)LOAD_ARG0();
|
uint32_t addr = (uint32_t)LOAD_ARG0();
|
||||||
A1 v = LOAD_ARG1();
|
A1 v = LOAD_ARG1();
|
||||||
ctx->WF64(ctx, addr, v);
|
memory->WF64(addr, v);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,7 +755,7 @@ CALLBACK(BRANCH_INDIRECT) {
|
||||||
CALLBACK(CALL_EXTERNAL) {
|
CALLBACK(CALL_EXTERNAL) {
|
||||||
A0 addr = LOAD_ARG0();
|
A0 addr = LOAD_ARG0();
|
||||||
void (*func)(void *) = (void (*)(void *))(intptr_t)addr;
|
void (*func)(void *) = (void (*)(void *))(intptr_t)addr;
|
||||||
func(ctx->guest_ctx);
|
func(guest_ctx);
|
||||||
return NEXT_INSTR;
|
return NEXT_INSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,4 +10,6 @@ X64Block::X64Block(int guest_cycles) : RuntimeBlock(guest_cycles) {}
|
||||||
|
|
||||||
X64Block::~X64Block() {}
|
X64Block::~X64Block() {}
|
||||||
|
|
||||||
uint32_t X64Block::Call(RuntimeContext &runtime_ctx) { return 0xdeadbeef; }
|
uint32_t X64Block::Call(emu::Memory *memory, void *guest_ctx) {
|
||||||
|
return 0xdeadbeef;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class X64Block : public RuntimeBlock {
|
||||||
X64Block(int guest_cycles);
|
X64Block(int guest_cycles);
|
||||||
~X64Block();
|
~X64Block();
|
||||||
|
|
||||||
uint32_t Call(RuntimeContext &runtime_ctx);
|
uint32_t Call(emu::Memory *memory, void *guest_ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,10 +9,6 @@ using namespace dreavm::cpu::frontend::sh4;
|
||||||
using namespace dreavm::cpu::ir;
|
using namespace dreavm::cpu::ir;
|
||||||
using namespace dreavm::emu;
|
using namespace dreavm::emu;
|
||||||
|
|
||||||
void SRUpdated(SH4Context *ctx) { ctx->SRUpdated(); }
|
|
||||||
|
|
||||||
void FPSCRUpdated(SH4Context *ctx) { ctx->FPSCRUpdated(); }
|
|
||||||
|
|
||||||
SH4Builder::SH4Builder(Memory &memory)
|
SH4Builder::SH4Builder(Memory &memory)
|
||||||
: memory_(memory), has_delay_instr_(false), last_instr_(nullptr) {}
|
: memory_(memory), has_delay_instr_(false), last_instr_(nullptr) {}
|
||||||
|
|
||||||
|
|
|
@ -13,54 +13,6 @@ using namespace dreavm::cpu;
|
||||||
using namespace dreavm::cpu::ir;
|
using namespace dreavm::cpu::ir;
|
||||||
using namespace dreavm::emu;
|
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)
|
Runtime::Runtime(Memory &memory)
|
||||||
: memory_(memory),
|
: memory_(memory),
|
||||||
frontend_(nullptr),
|
frontend_(nullptr),
|
||||||
|
@ -68,20 +20,6 @@ Runtime::Runtime(Memory &memory)
|
||||||
pending_reset_(false) {
|
pending_reset_(false) {
|
||||||
blocks_ = new std::unique_ptr<RuntimeBlock>[MAX_BLOCKS];
|
blocks_ = new std::unique_ptr<RuntimeBlock>[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<Pass>(new ValidateBlockPass()));
|
pass_runner_.AddPass(std::unique_ptr<Pass>(new ValidateBlockPass()));
|
||||||
pass_runner_.AddPass(std::unique_ptr<Pass>(new ControlFlowAnalysisPass()));
|
pass_runner_.AddPass(std::unique_ptr<Pass>(new ControlFlowAnalysisPass()));
|
||||||
pass_runner_.AddPass(std::unique_ptr<Pass>(new ContextPromotionPass()));
|
pass_runner_.AddPass(std::unique_ptr<Pass>(new ContextPromotionPass()));
|
||||||
|
|
|
@ -31,25 +31,6 @@ static inline uint32_t BlockOffset(uint32_t addr) {
|
||||||
class Runtime;
|
class Runtime;
|
||||||
class RuntimeBlock;
|
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 {
|
class RuntimeBlock {
|
||||||
public:
|
public:
|
||||||
RuntimeBlock(int guest_cycles) : guest_cycles_(guest_cycles) {}
|
RuntimeBlock(int guest_cycles) : guest_cycles_(guest_cycles) {}
|
||||||
|
@ -57,7 +38,7 @@ class RuntimeBlock {
|
||||||
|
|
||||||
int guest_cycles() { return guest_cycles_; }
|
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:
|
private:
|
||||||
int guest_cycles_;
|
int guest_cycles_;
|
||||||
|
@ -69,7 +50,6 @@ class Runtime {
|
||||||
~Runtime();
|
~Runtime();
|
||||||
|
|
||||||
emu::Memory &memory() { return memory_; }
|
emu::Memory &memory() { return memory_; }
|
||||||
RuntimeContext &ctx() { return runtime_ctx_; }
|
|
||||||
|
|
||||||
bool Init(frontend::Frontend *frontend, backend::Backend *backend);
|
bool Init(frontend::Frontend *frontend, backend::Backend *backend);
|
||||||
RuntimeBlock *ResolveBlock(uint32_t addr);
|
RuntimeBlock *ResolveBlock(uint32_t addr);
|
||||||
|
@ -82,7 +62,6 @@ class Runtime {
|
||||||
emu::Memory &memory_;
|
emu::Memory &memory_;
|
||||||
frontend::Frontend *frontend_;
|
frontend::Frontend *frontend_;
|
||||||
backend::Backend *backend_;
|
backend::Backend *backend_;
|
||||||
RuntimeContext runtime_ctx_;
|
|
||||||
ir::PassRunner pass_runner_;
|
ir::PassRunner pass_runner_;
|
||||||
// FIXME 64 mb, could cut down to 8 mb if indices were stored instead of
|
// FIXME 64 mb, could cut down to 8 mb if indices were stored instead of
|
||||||
// pointers
|
// pointers
|
||||||
|
|
|
@ -14,63 +14,6 @@ InterruptInfo interrupts[NUM_INTERRUPTS] = {
|
||||||
#undef SH4_INT
|
#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)
|
SH4::SH4(emu::Scheduler &scheduler, Memory &memory)
|
||||||
: scheduler_(scheduler), memory_(memory) {}
|
: scheduler_(scheduler), memory_(memory) {}
|
||||||
|
|
||||||
|
@ -78,9 +21,6 @@ SH4::~SH4() {}
|
||||||
|
|
||||||
bool SH4::Init(Runtime *runtime) {
|
bool SH4::Init(Runtime *runtime) {
|
||||||
runtime_ = runtime;
|
runtime_ = runtime;
|
||||||
if (runtime_) {
|
|
||||||
runtime_->ctx().guest_ctx = &ctx_;
|
|
||||||
}
|
|
||||||
|
|
||||||
scheduler_.AddDevice(this);
|
scheduler_.AddDevice(this);
|
||||||
|
|
||||||
|
@ -108,7 +48,7 @@ int64_t SH4::Execute(int64_t cycles) {
|
||||||
RuntimeBlock *block = runtime_->ResolveBlock(ctx_.pc);
|
RuntimeBlock *block = runtime_->ResolveBlock(ctx_.pc);
|
||||||
CHECK(block);
|
CHECK(block);
|
||||||
|
|
||||||
uint32_t nextpc = block->Call(runtime_->ctx());
|
uint32_t nextpc = block->Call(&memory_, &ctx_);
|
||||||
remaining -= block->guest_cycles();
|
remaining -= block->guest_cycles();
|
||||||
ctx_.pc = nextpc;
|
ctx_.pc = nextpc;
|
||||||
|
|
||||||
|
@ -316,8 +256,8 @@ void SH4::InitMemory() {
|
||||||
void SH4::InitContext() {
|
void SH4::InitContext() {
|
||||||
memset(&ctx_, 0, sizeof(ctx_));
|
memset(&ctx_, 0, sizeof(ctx_));
|
||||||
ctx_.sh4 = this;
|
ctx_.sh4 = this;
|
||||||
// ctx_.pc = 0xa0000000;
|
ctx_.pc = 0xa0000000;
|
||||||
ctx_.pc = 0x0c010000;
|
// ctx_.pc = 0x0c010000;
|
||||||
ctx_.pr = 0xdeadbeef;
|
ctx_.pr = 0xdeadbeef;
|
||||||
#define SH4_REG(addr, name, flags, default, reset, sleep, standby, type) \
|
#define SH4_REG(addr, name, flags, default, reset, sleep, standby, type) \
|
||||||
if (default != HELD) { \
|
if (default != HELD) { \
|
||||||
|
@ -399,10 +339,7 @@ void SH4::CheckPendingInterrupts() {
|
||||||
ctx_.sr.BL = 1;
|
ctx_.sr.BL = 1;
|
||||||
ctx_.sr.MD = 1;
|
ctx_.sr.MD = 1;
|
||||||
ctx_.sr.RB = 1;
|
ctx_.sr.RB = 1;
|
||||||
if (ctx_.old_sr.RB != ctx_.sr.RB) {
|
SRUpdated(&ctx_);
|
||||||
ctx_.SetRegisterBank(1);
|
|
||||||
}
|
|
||||||
ctx_.old_sr = ctx_.sr;
|
|
||||||
ctx_.pc = ctx_.vbr + 0x600;
|
ctx_.pc = ctx_.vbr + 0x600;
|
||||||
if (ctx_.sleep_mode == 1) {
|
if (ctx_.sleep_mode == 1) {
|
||||||
ctx_.sleep_mode = 2;
|
ctx_.sleep_mode = 2;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef SH4_H
|
#ifndef SH4_H
|
||||||
#define SH4_H
|
#define SH4_H
|
||||||
|
|
||||||
|
#include "cpu/sh4_context.h"
|
||||||
#include "emu/device.h"
|
#include "emu/device.h"
|
||||||
#include "emu/memory.h"
|
#include "emu/memory.h"
|
||||||
#include "emu/scheduler.h"
|
#include "emu/scheduler.h"
|
||||||
|
@ -12,8 +13,6 @@ namespace cpu {
|
||||||
|
|
||||||
class Runtime;
|
class Runtime;
|
||||||
|
|
||||||
enum { MAX_FRAMES = 4096 };
|
|
||||||
|
|
||||||
// registers
|
// registers
|
||||||
enum {
|
enum {
|
||||||
UNDEFINED = 0x0,
|
UNDEFINED = 0x0,
|
||||||
|
@ -48,40 +47,6 @@ union CCR_T {
|
||||||
uint32_t full;
|
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 {
|
union CHCR_T {
|
||||||
struct {
|
struct {
|
||||||
uint32_t DE : 1;
|
uint32_t DE : 1;
|
||||||
|
@ -140,40 +105,8 @@ enum DDTRW { //
|
||||||
DDT_W
|
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 {
|
class SH4 : public emu::Device {
|
||||||
friend class SH4Context;
|
friend void SRUpdated(SH4Context *ctx);
|
||||||
friend void RunSH4Test(const SH4Test &);
|
friend void RunSH4Test(const SH4Test &);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -205,10 +138,10 @@ class SH4 : public emu::Device {
|
||||||
void InitMemory();
|
void InitMemory();
|
||||||
void InitContext();
|
void InitContext();
|
||||||
|
|
||||||
SH4Context ctx_;
|
|
||||||
emu::Scheduler &scheduler_;
|
emu::Scheduler &scheduler_;
|
||||||
emu::Memory &memory_;
|
emu::Memory &memory_;
|
||||||
Runtime *runtime_;
|
Runtime *runtime_;
|
||||||
|
SH4Context ctx_;
|
||||||
#define SH4_REG(addr, name, flags, default, reset, sleep, standby, type) \
|
#define SH4_REG(addr, name, flags, default, reset, sleep, standby, type) \
|
||||||
type &name{reinterpret_cast<type &>(ctx_.m[name##_OFFSET])};
|
type &name{reinterpret_cast<type &>(ctx_.m[name##_OFFSET])};
|
||||||
#include "cpu/sh4_regs.inc"
|
#include "cpu/sh4_regs.inc"
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef SH4_CONTEXT_H
|
||||||
|
#define SH4_CONTEXT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
|
@ -20,27 +20,20 @@ using namespace dreavm::system;
|
||||||
|
|
||||||
Emulator::Emulator(System &sys)
|
Emulator::Emulator(System &sys)
|
||||||
: sys_(sys),
|
: sys_(sys),
|
||||||
scheduler_(new Scheduler()),
|
runtime_(memory_),
|
||||||
memory_(new Memory()),
|
processor_(scheduler_, memory_),
|
||||||
rt_frontend_(new SH4Frontend(*memory_)),
|
holly_(scheduler_, memory_, processor_) {
|
||||||
rt_backend_(new InterpreterBackend(*memory_)),
|
rt_frontend_ = new SH4Frontend(memory_);
|
||||||
// rt_backend_(new X64Backend(*memory_)),
|
rt_backend_ = new InterpreterBackend(memory_);
|
||||||
runtime_(new Runtime(*memory_)),
|
// rt_backend_ = new X64Backend(*memory_);
|
||||||
processor_(new SH4(*scheduler_, *memory_)),
|
|
||||||
holly_(new Holly(*scheduler_, *memory_, *processor_)) {
|
|
||||||
rb_ = new GLBackend(sys);
|
rb_ = new GLBackend(sys);
|
||||||
}
|
}
|
||||||
|
|
||||||
Emulator::~Emulator() {
|
Emulator::~Emulator() {
|
||||||
Profiler::Shutdown();
|
Profiler::Shutdown();
|
||||||
delete rb_;
|
delete rb_;
|
||||||
delete holly_;
|
|
||||||
delete processor_;
|
|
||||||
delete runtime_;
|
|
||||||
delete rt_backend_;
|
delete rt_backend_;
|
||||||
delete rt_frontend_;
|
delete rt_frontend_;
|
||||||
delete memory_;
|
|
||||||
delete scheduler_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Emulator::Init() {
|
bool Emulator::Init() {
|
||||||
|
@ -64,17 +57,17 @@ bool Emulator::Init() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runtime_->Init(rt_frontend_, rt_backend_)) {
|
if (!runtime_.Init(rt_frontend_, rt_backend_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// order here is important, sh4 memory handlers need to override
|
// order here is important, sh4 memory handlers need to override
|
||||||
// some of the broader holly handlers
|
// some of the broader holly handlers
|
||||||
if (!holly_->Init(rb_)) {
|
if (!holly_.Init(rb_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!processor_->Init(runtime_)) {
|
if (!processor_.Init(&runtime_)) {
|
||||||
return false;
|
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
|
// load to 0x0c010000 (area 3) which is where 1ST_READ.BIN is normally
|
||||||
// loaded to
|
// loaded to
|
||||||
memory_->Memcpy(0x0c010000, data, size);
|
memory_.Memcpy(0x0c010000, data, size);
|
||||||
free(data);
|
free(data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +107,7 @@ bool Emulator::LaunchGDI(const char *path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
holly_->gdrom().SetDisc(std::move(gdi));
|
holly_.gdrom().SetDisc(std::move(gdi));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -122,14 +115,14 @@ bool Emulator::LaunchGDI(const char *path) {
|
||||||
void Emulator::Tick() {
|
void Emulator::Tick() {
|
||||||
PumpEvents();
|
PumpEvents();
|
||||||
|
|
||||||
scheduler_->Tick();
|
scheduler_.Tick();
|
||||||
|
|
||||||
RenderFrame();
|
RenderFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
// for memory mapping notes, see 2.1 System Mapping in the hardware manual
|
// for memory mapping notes, see 2.1 System Mapping in the hardware manual
|
||||||
bool Emulator::MountRam() {
|
bool Emulator::MountRam() {
|
||||||
memory_->Alloc(0x0, 0x1fffffff, 0xe0000000);
|
memory_.Alloc(0x0, 0x1fffffff, 0xe0000000);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +157,7 @@ bool Emulator::LoadBios(const char *path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_->Memcpy(BIOS_START, data, size);
|
memory_.Memcpy(BIOS_START, data, size);
|
||||||
free(data);
|
free(data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +193,7 @@ bool Emulator::LoadFlash(const char *path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_->Memcpy(FLASH_START, data, size);
|
memory_.Memcpy(FLASH_START, data, size);
|
||||||
free(data);
|
free(data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +205,7 @@ void Emulator::PumpEvents() {
|
||||||
// let the profiler take a stab at the input first
|
// let the profiler take a stab at the input first
|
||||||
if (!Profiler::HandleInput(ev.key.code, ev.key.value)) {
|
if (!Profiler::HandleInput(ev.key.code, ev.key.value)) {
|
||||||
// else, forward to holly
|
// 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) {
|
} else if (ev.type == SE_MOUSEMOVE) {
|
||||||
Profiler::HandleMouseMove(ev.mousemove.x, ev.mousemove.y);
|
Profiler::HandleMouseMove(ev.mousemove.x, ev.mousemove.y);
|
||||||
|
@ -231,7 +224,7 @@ void Emulator::RenderFrame() {
|
||||||
// render stats
|
// render stats
|
||||||
char stats[512];
|
char stats[512];
|
||||||
snprintf(stats, sizeof(stats), "%.2f%%, %.2f fps, %.2f vbps",
|
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;
|
LOG_EVERY_N(INFO, 10) << stats;
|
||||||
rb_->RenderText2D(0.0f, 0.0f, 12, 0xffffffff, stats);
|
rb_->RenderText2D(0.0f, 0.0f, 12, 0xffffffff, stats);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "cpu/sh4.h"
|
#include "cpu/sh4.h"
|
||||||
#include "cpu/backend/backend.h"
|
#include "cpu/backend/backend.h"
|
||||||
#include "cpu/frontend/frontend.h"
|
#include "cpu/frontend/frontend.h"
|
||||||
|
#include "cpu/runtime.h"
|
||||||
#include "holly/holly.h"
|
#include "holly/holly.h"
|
||||||
#include "holly/maple_controller.h"
|
#include "holly/maple_controller.h"
|
||||||
#include "renderer/backend.h"
|
#include "renderer/backend.h"
|
||||||
|
@ -31,13 +32,13 @@ class Emulator {
|
||||||
void RenderFrame();
|
void RenderFrame();
|
||||||
|
|
||||||
system::System &sys_;
|
system::System &sys_;
|
||||||
emu::Scheduler *scheduler_;
|
emu::Scheduler scheduler_;
|
||||||
emu::Memory *memory_;
|
emu::Memory memory_;
|
||||||
|
cpu::Runtime runtime_;
|
||||||
|
cpu::SH4 processor_;
|
||||||
|
holly::Holly holly_;
|
||||||
cpu::frontend::Frontend *rt_frontend_;
|
cpu::frontend::Frontend *rt_frontend_;
|
||||||
cpu::backend::Backend *rt_backend_;
|
cpu::backend::Backend *rt_backend_;
|
||||||
cpu::Runtime *runtime_;
|
|
||||||
cpu::SH4 *processor_;
|
|
||||||
holly::Holly *holly_;
|
|
||||||
renderer::Backend *rb_;
|
renderer::Backend *rb_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,10 @@ int main(int argc, char **argv) {
|
||||||
LOG(FATAL) << "Failed to load bin.";
|
LOG(FATAL) << "Failed to load bin.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (!emu.LaunchGDI(
|
if (!emu.LaunchGDI(
|
||||||
// "../dreamcast/Crazy Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!]/Crazy "
|
"../dreamcast/Crazy Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!]/Crazy Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!].gdi")) {
|
||||||
// "Taxi 2 v1.004 (2001)(Sega)(NTSC)(US)[!].gdi")) {
|
LOG(FATAL) << "Failed to load GDI.";
|
||||||
// LOG(FATAL) << "Failed to load GDI.";
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
sys.Tick();
|
sys.Tick();
|
||||||
|
|
|
@ -20,7 +20,6 @@ namespace cpu {
|
||||||
void RunSH4Test(const SH4Test &test) {
|
void RunSH4Test(const SH4Test &test) {
|
||||||
Scheduler scheduler;
|
Scheduler scheduler;
|
||||||
Memory memory;
|
Memory memory;
|
||||||
SH4 sh4(scheduler, memory);
|
|
||||||
|
|
||||||
// initialize runtime
|
// initialize runtime
|
||||||
frontend::sh4::SH4Frontend sh4_frontend(memory);
|
frontend::sh4::SH4Frontend sh4_frontend(memory);
|
||||||
|
@ -29,6 +28,7 @@ void RunSH4Test(const SH4Test &test) {
|
||||||
ASSERT_TRUE(runtime.Init(&sh4_frontend, &int_backend));
|
ASSERT_TRUE(runtime.Init(&sh4_frontend, &int_backend));
|
||||||
|
|
||||||
// initialize device
|
// initialize device
|
||||||
|
SH4 sh4(scheduler, memory);
|
||||||
ASSERT_TRUE(sh4.Init(&runtime));
|
ASSERT_TRUE(sh4.Init(&runtime));
|
||||||
|
|
||||||
// mount the test binary and a small stack
|
// mount the test binary and a small stack
|
||||||
|
|
Loading…
Reference in New Issue