moved interpeter code to its own backend

setup code to work without x64 backend
This commit is contained in:
Anthony Pesch 2017-05-27 17:20:03 -04:00
parent 81c8f90add
commit 5fc185d4f1
24 changed files with 356 additions and 315 deletions

View File

@ -184,9 +184,7 @@ set(REDREAM_SOURCES
src/hw/dreamcast.c
src/hw/memory.c
src/hw/scheduler.c
src/jit/backend/x64/x64_backend.cc
src/jit/backend/x64/x64_disassembler.c
src/jit/backend/x64/x64_dispatch.cc
src/jit/backend/interp/interp_backend.c
src/jit/frontend/armv3/armv3_context.c
src/jit/frontend/armv3/armv3_disasm.c
src/jit/frontend/armv3/armv3_fallback.c
@ -221,25 +219,36 @@ set(REDREAM_SOURCES
if(PLATFORM_WINDOWS)
list(APPEND REDREAM_DEFS PLATFORM_WINDOWS=1)
list(APPEND REDREAM_SOURCES src/sys/exception_handler_win.c)
list(APPEND REDREAM_SOURCES src/sys/filesystem_win.c)
list(APPEND REDREAM_SOURCES src/sys/memory_win.c)
list(APPEND REDREAM_SOURCES src/sys/thread_win.c)
list(APPEND REDREAM_SOURCES src/sys/time_win.c)
list(APPEND REDREAM_SOURCES
src/sys/exception_handler_win.c
src/sys/filesystem_win.c
src/sys/memory_win.c
src/sys/thread_win.c
src/sys/time_win.c)
elseif(PLATFORM_DARWIN)
list(APPEND REDREAM_DEFS PLATFORM_DARWIN=1)
list(APPEND REDREAM_SOURCES src/sys/exception_handler_mac.c)
list(APPEND REDREAM_SOURCES src/sys/filesystem_posix.c)
list(APPEND REDREAM_SOURCES src/sys/memory_posix.c)
list(APPEND REDREAM_SOURCES src/sys/thread_posix.c)
list(APPEND REDREAM_SOURCES src/sys/time_mac.c)
list(APPEND REDREAM_SOURCES
src/sys/exception_handler_mac.c
src/sys/filesystem_posix.c
src/sys/memory_posix.c
src/sys/thread_posix.c
src/sys/time_mac.c)
elseif(PLATFORM_LINUX)
list(APPEND REDREAM_DEFS PLATFORM_LINUX=1)
list(APPEND REDREAM_SOURCES src/sys/exception_handler_linux.c)
list(APPEND REDREAM_SOURCES src/sys/filesystem_posix.c)
list(APPEND REDREAM_SOURCES src/sys/memory_posix.c)
list(APPEND REDREAM_SOURCES src/sys/thread_posix.c)
list(APPEND REDREAM_SOURCES src/sys/time_linux.c)
list(APPEND REDREAM_SOURCES
src/sys/exception_handler_linux.c
src/sys/filesystem_posix.c
src/sys/memory_posix.c
src/sys/thread_posix.c
src/sys/time_linux.c)
endif()
if(ARCH_X64)
list(APPEND REDREAM_DEFS ARCH_X64=1)
list(APPEND REDREAM_SOURCES
src/jit/backend/x64/x64_backend.cc
src/jit/backend/x64/x64_disassembler.c
src/jit/backend/x64/x64_dispatch.cc)
endif()
# assign source groups for visual studio projects
@ -322,12 +331,14 @@ target_compile_options(redream PRIVATE ${REDREAM_FLAGS})
if(BUILD_TOOLS)
if(ARCH_X64)
add_executable(recc $<TARGET_OBJECTS:relib> src/null_host.c tools/recc/main.c)
target_include_directories(recc SYSTEM PUBLIC ${REDREAM_INCLUDE_DIRS})
target_include_directories(recc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(recc ${REDREAM_LIBS})
target_compile_definitions(recc PRIVATE ${REDREAM_DEFS} MICROPROFILE_ENABLED=0)
target_compile_options(recc PRIVATE ${REDREAM_FLAGS})
endif()
add_executable(retrace $<TARGET_OBJECTS:relib>
src/null_host.c

View File

@ -1,10 +1,8 @@
#include <stdio.h>
#include "hw/arm7/arm7.h"
#include "core/log.h"
#include "hw/aica/aica.h"
#include "hw/dreamcast.h"
#include "hw/scheduler.h"
#include "jit/backend/x64/x64_backend.h"
#include "jit/frontend/armv3/armv3_context.h"
#include "jit/frontend/armv3/armv3_fallback.h"
#include "jit/frontend/armv3/armv3_frontend.h"
@ -12,6 +10,12 @@
#include "jit/ir/ir.h"
#include "jit/jit.h"
#if ARCH_X64
#include "jit/backend/x64/x64_backend.h"
#else
#include "jit/backend/interp/interp_backend.h"
#endif
DEFINE_AGGREGATE_COUNTER(arm7_instrs);
struct arm7 {
@ -23,8 +27,8 @@ struct arm7 {
/* jit */
struct jit *jit;
struct armv3_guest *guest;
struct armv3_frontend *frontend;
struct x64_backend *backend;
struct jit_frontend *frontend;
struct jit_backend *backend;
/* interrupts */
uint32_t requested_interrupts;
@ -158,33 +162,7 @@ static void arm7_run(struct device *dev, int64_t ns) {
static int64_t ARM7_CLOCK_FREQ = INT64_C(20000000);
int cycles = (int)NANO_TO_CYCLES(ns, ARM7_CLOCK_FREQ);
#if 1
jit_run(arm->jit, cycles);
#else
ctx->run_cycles = cycles;
ctx->ran_instrs = 0;
while (ctx->run_cycles > 0) {
static int RUN_SLICE = 64;
int ran_cycles = 0;
int ran_instrs = 0;
do {
uint32_t data = as_read32(arm->memory_if->space, ctx->r[15]);
union armv3_instr instr = {data};
armv3_fallback_cb cb = armv3_get_fallback(data);
cb(arm->guest, ctx->r[15], instr);
ran_cycles += 8;
ran_instrs++;
} while (ran_cycles < RUN_SLICE);
ctx->run_cycles -= ran_cycles;
ctx->ran_instrs += ran_instrs;
arm7_check_pending_interrupts(arm);
}
#endif
prof_counter_add(COUNTER_arm7_instrs, arm->ctx.ran_instrs);
@ -201,7 +179,13 @@ static int arm7_init(struct device *dev) {
static uint8_t arm7_code[0x800000];
/* initialize jit and its interfaces */
arm->jit = jit_create("arm7");
arm->frontend = armv3_frontend_create();
#if ARCH_X64
arm->backend = x64_backend_create(arm7_code, sizeof(arm7_code));
#else
arm->backend = interp_backend_create();
#endif
{
arm->guest = armv3_guest_create();
@ -230,14 +214,8 @@ static int arm7_init(struct device *dev) {
arm->guest->w32 = &as_write32;
}
arm->frontend = armv3_frontend_create(arm->jit);
arm->backend = x64_backend_create(arm->jit, arm7_code, sizeof(arm7_code));
if (!jit_init(arm->jit, (struct jit_guest *)arm->guest,
(struct jit_frontend *)arm->frontend,
(struct jit_backend *)arm->backend)) {
return 0;
}
arm->jit = jit_create("arm7", arm->frontend, arm->backend,
(struct jit_guest *)arm->guest);
arm->wave_ram = memory_translate(dc->memory, "aica wave ram", 0x00000000);
@ -246,9 +224,9 @@ static int arm7_init(struct device *dev) {
void arm7_destroy(struct arm7 *arm) {
jit_destroy(arm->jit);
armv3_frontend_destroy(arm->frontend);
x64_backend_destroy(arm->backend);
armv3_guest_destroy(arm->guest);
arm->frontend->destroy(arm->frontend);
arm->backend->destroy(arm->backend);
dc_destroy_memory_interface(arm->memory_if);
dc_destroy_execute_interface(arm->execute_if);

View File

@ -10,7 +10,6 @@
#include "hw/rom/boot.h"
#include "hw/rom/flash.h"
#include "hw/scheduler.h"
#include "jit/backend/x64/x64_backend.h"
#include "jit/frontend/sh4/sh4_fallback.h"
#include "jit/frontend/sh4/sh4_frontend.h"
#include "jit/frontend/sh4/sh4_guest.h"
@ -19,6 +18,12 @@
#include "render/nuklear.h"
#include "sys/time.h"
#if ARCH_X64
#include "jit/backend/x64/x64_backend.h"
#else
#include "jit/backend/interp/interp_backend.h"
#endif
DEFINE_AGGREGATE_COUNTER(sh4_instrs);
DEFINE_AGGREGATE_COUNTER(sh4_sr_updates);
@ -131,34 +136,7 @@ static void sh4_run(struct device *dev, int64_t ns) {
int cycles = (int)NANO_TO_CYCLES(ns, SH4_CLOCK_FREQ);
cycles = MAX(cycles, 1);
#if 1
jit_run(sh4->jit, cycles);
#else
ctx->run_cycles = cycles;
ctx->ran_instrs = 0;
while (ctx->run_cycles > 0) {
static int RUN_SLICE = 64;
int ran_cycles = 0;
int ran_instrs = 0;
do {
uint16_t data = as_read16(sh4->memory_if->space, ctx->pc);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data);
sh4_fallback_cb cb = sh4_get_fallback(data);
cb(sh4->guest, ctx->pc, instr);
ran_cycles += def->cycles;
ran_instrs++;
} while (ran_cycles < RUN_SLICE);
ctx->run_cycles -= ran_cycles;
ctx->ran_instrs += ran_instrs;
sh4_intc_check_pending(sh4);
}
#endif
prof_counter_add(COUNTER_sh4_instrs, sh4->ctx.ran_instrs);
@ -202,7 +180,13 @@ static int sh4_init(struct device *dev) {
RIP-relative offsets when calling functions */
static uint8_t sh4_code[0x800000];
sh4->jit = jit_create("sh4");
sh4->frontend = sh4_frontend_create();
#if ARCH_X64
sh4->backend = x64_backend_create(sh4_code, sizeof(sh4_code));
#else
sh4->backend = interp_backend_create();
#endif
{
sh4->guest = sh4_guest_create();
@ -233,23 +217,17 @@ static int sh4_init(struct device *dev) {
sh4->guest->w32 = &as_write32;
}
sh4->frontend = sh4_frontend_create(sh4->jit);
sh4->backend = x64_backend_create(sh4->jit, sh4_code, sizeof(sh4_code));
if (!jit_init(sh4->jit, (struct jit_guest *)sh4->guest,
(struct jit_frontend *)sh4->frontend,
(struct jit_backend *)sh4->backend)) {
return 0;
}
sh4->jit = jit_create("sh4", sh4->frontend, sh4->backend,
(struct jit_guest *)sh4->guest);
return 1;
}
void sh4_destroy(struct sh4 *sh4) {
jit_destroy(sh4->jit);
sh4_frontend_destroy(sh4->frontend);
x64_backend_destroy(sh4->backend);
sh4_guest_destroy(sh4->guest);
sh4->frontend->destroy(sh4->frontend);
sh4->backend->destroy(sh4->backend);
dc_destroy_memory_interface(sh4->memory_if);
dc_destroy_execute_interface(sh4->execute_if);

View File

@ -10,9 +10,9 @@
struct dreamcast;
struct jit;
struct sh4_frontend;
struct jit_backend;
struct jit_frontend;
struct sh4_guest;
struct x64_backend;
#define SH4_CLOCK_FREQ INT64_C(200000000)
@ -48,8 +48,8 @@ struct sh4 {
/* jit */
struct jit *jit;
struct sh4_guest *guest;
struct sh4_frontend *frontend;
struct x64_backend *backend;
struct jit_frontend *frontend;
struct jit_backend *backend;
/* dbg */
struct list breakpoints;

View File

@ -129,10 +129,8 @@ void sh4_dbg_step(struct device *dev) {
/* run the fallback handler for the current pc */
uint16_t data = as_read16(sh4->memory_if->space, sh4->ctx.pc);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data);
sh4_fallback_cb cb = sh4_get_fallback(data);
cb(sh4->guest, sh4->ctx.pc, instr);
def->fallback((struct jit_guest *)sh4->guest, sh4->ctx.pc, data);
/* let the debugger know we've stopped */
debugger_trap(sh4->dc->debugger);

View File

@ -0,0 +1,87 @@
#include <stdlib.h>
#include "jit/backend/jit_backend.h"
#include "jit/frontend/jit_frontend.h"
#include "jit/jit.h"
struct interp_backend {
struct jit_backend;
};
static void interp_backend_run_code(struct jit_backend *base, int cycles) {
struct interp_backend *backend = (struct interp_backend *)base;
struct jit *jit = backend->jit;
struct jit_guest *guest = jit->guest;
void *ctx = guest->ctx;
uint32_t *pc = ctx + guest->offset_pc;
int32_t *run_cycles = ctx + guest->offset_cycles;
int32_t *ran_instrs = ctx + guest->offset_instrs;
*run_cycles = cycles;
*ran_instrs = 0;
while (*run_cycles > 0) {
static int RUN_SLICE = 64;
int cycles = 0;
int instrs = 0;
do {
uint32_t addr = *pc;
uint32_t data = guest->r32(guest->space, addr);
const struct jit_opdef *def =
jit->frontend->lookup_op(jit->frontend, &data);
def->fallback(guest, addr, data);
cycles += def->cycles;
instrs += 1;
} while (cycles < RUN_SLICE);
*run_cycles -= cycles;
*ran_instrs += instrs;
guest->interrupt_check(guest->data);
}
}
static int interp_backend_handle_exception(struct jit_backend *base,
struct exception *ex) {
return 0;
}
static void interp_backend_dump_code(struct jit_backend *base,
const uint8_t *code, int size) {}
static void interp_backend_reset(struct jit_backend *base) {}
static void interp_backend_destroy(struct jit_backend *base) {
struct interp_backend *backend = (struct interp_backend *)base;
free(backend);
}
static void interp_backend_init(struct jit_backend *base) {
struct interp_backend *backend = (struct interp_backend *)base;
}
struct jit_backend *interp_backend_create() {
struct interp_backend *backend = calloc(1, sizeof(struct interp_backend));
backend->init = &interp_backend_init;
backend->destroy = &interp_backend_destroy;
/* compile interface */
backend->registers = NULL;
backend->num_registers = 0;
backend->reset = &interp_backend_reset;
backend->assemble_code = NULL;
backend->dump_code = &interp_backend_dump_code;
backend->handle_exception = &interp_backend_handle_exception;
/* dispatch interface */
backend->run_code = &interp_backend_run_code;
backend->lookup_code = NULL;
backend->cache_code = NULL;
backend->invalidate_code = NULL;
backend->patch_edge = NULL;
backend->restore_edge = NULL;
return (struct jit_backend *)backend;
}

View File

@ -0,0 +1,8 @@
#ifndef INTERP_BACKEND_H
#define INTERP_BACKEND_H
#include "jit/backend/jit_backend.h"
struct jit_backend *interp_backend_create();
#endif

View File

@ -20,22 +20,22 @@ struct jit_backend {
const struct jit_register *registers;
int num_registers;
void (*init)(struct jit_backend *base);
void (*init)(struct jit_backend *);
void (*destroy)(struct jit_backend *);
/* compile interface */
void (*reset)(struct jit_backend *base);
int (*assemble_code)(struct jit_backend *base, struct jit_block *block,
struct ir *ir);
void (*dump_code)(struct jit_backend *base, const uint8_t *code, int size);
int (*handle_exception)(struct jit_backend *base, struct exception *ex);
void (*reset)(struct jit_backend *);
int (*assemble_code)(struct jit_backend *, struct jit_block *, struct ir *);
void (*dump_code)(struct jit_backend *, const uint8_t *, int);
int (*handle_exception)(struct jit_backend *, struct exception *);
/* dispatch interface */
void (*run_code)(struct jit_backend *base, int cycles);
void *(*lookup_code)(struct jit_backend *base, uint32_t);
void (*cache_code)(struct jit_backend *base, uint32_t, void *);
void (*invalidate_code)(struct jit_backend *base, uint32_t);
void (*patch_edge)(struct jit_backend *base, void *, void *);
void (*restore_edge)(struct jit_backend *base, void *, uint32_t);
void (*run_code)(struct jit_backend *, int);
void *(*lookup_code)(struct jit_backend *, uint32_t);
void (*cache_code)(struct jit_backend *, uint32_t, void *);
void (*invalidate_code)(struct jit_backend *, uint32_t);
void (*patch_edge)(struct jit_backend *, void *, void *);
void (*restore_edge)(struct jit_backend *, void *, uint32_t);
};
#endif

View File

@ -1727,6 +1727,18 @@ EMITTER(ASSERT_LT) {
e.outLocalLabel();
}
static void x64_backend_destroy(struct jit_backend *base) {
struct x64_backend *backend = container_of(base, struct x64_backend, base);
cs_close(&backend->capstone_handle);
delete backend->codegen;
x64_dispatch_shutdown(backend);
free(backend);
}
static void x64_backend_init(struct jit_backend *base) {
struct x64_backend *backend = container_of(base, struct x64_backend, base);
@ -1740,26 +1752,15 @@ static void x64_backend_init(struct jit_backend *base) {
x64_backend_reset(base);
}
void x64_backend_destroy(struct x64_backend *backend) {
cs_close(&backend->capstone_handle);
delete backend->codegen;
x64_dispatch_shutdown(backend);
free(backend);
}
struct x64_backend *x64_backend_create(struct jit *jit, void *code,
int code_size) {
struct jit_backend *x64_backend_create(void *code, int code_size) {
struct x64_backend *backend = reinterpret_cast<struct x64_backend *>(
calloc(1, sizeof(struct x64_backend)));
Xbyak::util::Cpu cpu;
CHECK(Xbyak::CodeArray::protect(code, code_size, true));
backend->base.jit = jit;
backend->base.init = &x64_backend_init;
backend->base.destroy = &x64_backend_destroy;
/* compile interface */
backend->base.registers = x64_registers;
@ -1783,5 +1784,5 @@ struct x64_backend *x64_backend_create(struct jit *jit, void *code,
int res = cs_open(CS_ARCH_X86, CS_MODE_64, &backend->capstone_handle);
CHECK_EQ(res, CS_ERR_OK);
return backend;
return &backend->base;
}

View File

@ -3,13 +3,6 @@
#include "jit/backend/jit_backend.h"
extern const struct jit_register x64_registers[];
extern const int x64_num_registers;
struct x64_backend;
struct x64_backend *x64_backend_create(struct jit *jit, void *code,
int code_size);
void x64_backend_destroy(struct x64_backend *backend);
struct jit_backend *x64_backend_create(void *code, int code_size);
#endif

View File

@ -2,13 +2,15 @@
#include "core/assert.h"
#include "core/constructor.h"
#include "core/string.h"
#include "jit/frontend/armv3/armv3_fallback.h"
int armv3_optable[ARMV3_LOOKUP_SIZE];
struct jit_opdef armv3_opdefs[NUM_ARMV3_OPS] = {
{ARMV3_OP_INVALID, NULL, NULL, 0, 0},
{ARMV3_OP_INVALID, NULL, NULL, 0, 0, NULL},
#define ARMV3_INSTR(name, desc, sig, cycles, flags) \
{ARMV3_OP_##name, desc, #sig, cycles, flags},
{ARMV3_OP_##name, desc, #sig, \
cycles, flags, (jit_fallback)&armv3_fallback_##name},
#include "armv3_instr.inc"
#undef ARMV3_INSTR
};

View File

@ -6,21 +6,6 @@
#include "jit/frontend/armv3/armv3_disasm.h"
#include "jit/frontend/armv3/armv3_guest.h"
/* forward declare each fallback */
#define ARMV3_INSTR(name, desc, sig, cycles, flags) \
static void armv3_fallback_##name(struct armv3_guest *guest, uint32_t addr, \
union armv3_instr i);
#include "armv3_instr.inc"
#undef ARMV3_INSTR
/* generate fallback lookup table */
armv3_fallback_cb armv3_fallbacks[NUM_ARMV3_OPS] = {
NULL,
#define ARMV3_INSTR(name, desc, sig, cycles, flags) &armv3_fallback_##name,
#include "armv3_instr.inc"
#undef ARMV3_INSTR
};
/* helper functions / macros for writing fallbacks */
#define FALLBACK(op) \
void armv3_fallback_##op(struct armv3_guest *guest, uint32_t addr, \
@ -800,7 +785,3 @@ FALLBACK(SWI) {
REG(15) = addr + 4;
guest->software_interrupt(guest->data);
}
void *armv3_fallback(uint32_t instr) {
return armv3_fallbacks[armv3_get_op(instr)];
}

View File

@ -5,13 +5,10 @@
struct armv3_guest;
typedef void (*armv3_fallback_cb)(struct armv3_guest *, uint32_t,
union armv3_instr);
extern armv3_fallback_cb armv3_fallbacks[NUM_ARMV3_OPS];
static inline armv3_fallback_cb armv3_get_fallback(uint32_t instr) {
return armv3_fallbacks[armv3_get_op(instr)];
}
#define ARMV3_INSTR(name, desc, sig, cycles, flags) \
void armv3_fallback_##name(struct armv3_guest *guest, uint32_t addr, \
union armv3_instr i);
#include "jit/frontend/armv3/armv3_instr.inc"
#undef ARMV3_INSTR
#endif

View File

@ -45,31 +45,9 @@ static void armv3_analyze_block(const struct armv3_guest *guest,
}
}
static void armv3_frontend_translate_code(struct jit_frontend *base,
struct jit_block *block,
struct ir *ir) {
struct armv3_frontend *frontend = (struct armv3_frontend *)base;
struct armv3_guest *guest = (struct armv3_guest *)frontend->jit->guest;
armv3_analyze_block(guest, block);
/* emit fallbacks */
uint32_t addr = block->guest_addr;
uint32_t end = block->guest_addr + block->guest_size;
while (addr < end) {
uint32_t instr = guest->r32(guest->space, addr);
armv3_fallback_cb fallback = armv3_get_fallback(instr);
ir_fallback(ir, fallback, addr, instr);
addr += 4;
}
/* branch to the current pc */
struct ir_value *pc =
ir_load_context(ir, offsetof(struct armv3_context, r[15]), VALUE_I32);
ir_branch(ir, pc);
static const struct jit_opdef *armv3_frontend_lookup_op(
struct jit_frontend *base, const void *instr) {
return armv3_get_opdef(*(const uint32_t *)instr);
}
static void armv3_frontend_dump_code(struct jit_frontend *base, uint32_t addr,
@ -89,19 +67,49 @@ static void armv3_frontend_dump_code(struct jit_frontend *base, uint32_t addr,
}
}
static void armv3_frontend_init(struct jit_frontend *frontend) {}
static void armv3_frontend_translate_code(struct jit_frontend *base,
struct jit_block *block,
struct ir *ir) {
struct armv3_frontend *frontend = (struct armv3_frontend *)base;
struct armv3_guest *guest = (struct armv3_guest *)frontend->jit->guest;
armv3_analyze_block(guest, block);
/* emit fallbacks */
uint32_t addr = block->guest_addr;
uint32_t end = block->guest_addr + block->guest_size;
while (addr < end) {
uint32_t data = guest->r32(guest->space, addr);
struct jit_opdef *def = armv3_get_opdef(data);
ir_fallback(ir, def->fallback, addr, data);
addr += 4;
}
/* branch to the current pc */
struct ir_value *pc =
ir_load_context(ir, offsetof(struct armv3_context, r[15]), VALUE_I32);
ir_branch(ir, pc);
}
void armv3_frontend_destroy(struct jit_frontend *base) {
struct armv3_frontend *frontend = (struct armv3_frontend *)base;
void armv3_frontend_destroy(struct armv3_frontend *frontend) {
free(frontend);
}
struct armv3_frontend *armv3_frontend_create(struct jit *jit) {
static void armv3_frontend_init(struct jit_frontend *frontend) {}
struct jit_frontend *armv3_frontend_create() {
struct armv3_frontend *frontend = calloc(1, sizeof(struct armv3_frontend));
frontend->jit = jit;
frontend->init = &armv3_frontend_init;
frontend->destroy = &armv3_frontend_destroy;
frontend->translate_code = &armv3_frontend_translate_code;
frontend->dump_code = &armv3_frontend_dump_code;
frontend->lookup_op = &armv3_frontend_lookup_op;
return frontend;
return (struct jit_frontend *)frontend;
}

View File

@ -3,15 +3,10 @@
#include "jit/frontend/jit_frontend.h"
struct jit;
enum armv3_block_flags {
PC_SET = 0x1,
};
struct armv3_frontend;
struct armv3_frontend *armv3_frontend_create(struct jit *jit);
void armv3_frontend_destroy(struct armv3_frontend *frontend);
struct jit_frontend *armv3_frontend_create();
#endif

View File

@ -6,23 +6,31 @@
struct ir;
struct jit;
struct jit_block;
struct jit_guest;
struct jit_frontend;
typedef void (*jit_fallback)(struct jit_guest *, uint32_t, uint32_t);
struct jit_opdef {
int op;
const char *desc;
const char *sig;
int cycles;
int flags;
jit_fallback fallback;
};
struct jit_frontend {
struct jit *jit;
void (*init)(struct jit_frontend *base);
void (*translate_code)(struct jit_frontend *base, struct jit_block *block,
struct ir *ir);
void (*dump_code)(struct jit_frontend *base, uint32_t addr, int size);
void (*init)(struct jit_frontend *);
void (*destroy)(struct jit_frontend *);
void (*translate_code)(struct jit_frontend *, struct jit_block *,
struct ir *);
void (*dump_code)(struct jit_frontend *, uint32_t, int);
const struct jit_opdef *(*lookup_op)(struct jit_frontend *, const void *);
};
#endif

View File

@ -2,12 +2,14 @@
#include "core/assert.h"
#include "core/constructor.h"
#include "core/string.h"
#include "jit/frontend/sh4/sh4_fallback.h"
int sh4_optable[UINT16_MAX + 1];
struct jit_opdef sh4_opdefs[NUM_SH4_OPS] = {
#define SH4_INSTR(name, desc, sig, cycles, flags) \
{SH4_OP_##name, desc, #sig, cycles, flags},
{SH4_OP_##name, desc, #sig, \
cycles, flags, (jit_fallback)&sh4_fallback_##name},
#include "jit/frontend/sh4/sh4_instr.inc"
#undef SH4_INSTR
};

View File

@ -61,13 +61,11 @@ typedef int32_t int128_t[4];
#define FPU_DOUBLE_PR (CTX->fpscr & PR_MASK)
#define FPU_DOUBLE_SZ (CTX->fpscr & SZ_MASK)
#define DELAY_INSTR() { \
uint32_t delay_addr = addr + 2; \
uint16_t delay_data = guest->r16(guest->space, delay_addr); \
union sh4_instr delay_instr = {delay_data}; \
sh4_fallback_cb cb = sh4_get_fallback(delay_data); \
CHECK_NOTNULL(cb); \
cb(guest, delay_addr, delay_instr); \
#define DELAY_INSTR() { \
uint32_t delay_addr = addr + 2; \
uint16_t delay_data = guest->r16(guest->space, delay_addr); \
const struct jit_opdef *def = sh4_get_opdef(delay_data); \
def->fallback((struct jit_guest *)guest, delay_addr, delay_data); \
}
#define NEXT_INSTR() (CTX->pc = addr + 2)
#define NEXT_NEXT_INSTR() (CTX->pc = addr + 4)
@ -389,9 +387,3 @@ typedef int32_t int128_t[4];
union sh4_instr i)
#include "jit/frontend/sh4/sh4_instr.h"
#undef INSTR
sh4_fallback_cb sh4_fallbacks[NUM_SH4_OPS] = {
#define SH4_INSTR(name, desc, sig, cycles, flags) &sh4_fallback_##name,
#include "jit/frontend/sh4/sh4_instr.inc"
#undef SH4_INSTR
};

View File

@ -5,12 +5,10 @@
struct sh4_guest;
typedef void (*sh4_fallback_cb)(struct sh4_guest *, uint32_t, union sh4_instr);
extern sh4_fallback_cb sh4_fallbacks[NUM_SH4_OPS];
static inline sh4_fallback_cb sh4_get_fallback(uint16_t instr) {
return sh4_fallbacks[sh4_get_op(instr)];
}
#define SH4_INSTR(name, desc, sig, cycles, flags) \
void sh4_fallback_##name(struct sh4_guest *guest, uint32_t addr, \
union sh4_instr i);
#include "jit/frontend/sh4/sh4_instr.inc"
#undef SH4_INSTR
#endif

View File

@ -67,6 +67,42 @@ static void sh4_analyze_block(const struct sh4_guest *guest,
}
}
static const struct jit_opdef *sh4_frontend_lookup_op(struct jit_frontend *base,
const void *instr) {
return sh4_get_opdef(*(const uint16_t *)instr);
}
static void sh4_frontend_dump_code(struct jit_frontend *base, uint32_t addr,
int size) {
struct sh4_frontend *frontend = (struct sh4_frontend *)base;
struct jit_guest *guest = frontend->jit->guest;
char buffer[128];
uint32_t end = addr + size / 2;
while (addr < end) {
uint16_t data = guest->r16(guest->space, addr);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data);
sh4_format(addr, instr, buffer, sizeof(buffer));
LOG_INFO(buffer);
addr += 2;
if (def->flags & SH4_FLAG_DELAYED) {
uint16_t delay_data = guest->r16(guest->space, addr);
union sh4_instr delay_instr = {delay_data};
sh4_format(addr, delay_instr, buffer, sizeof(buffer));
LOG_INFO(buffer);
addr += 2;
}
}
}
static void sh4_frontend_translate_code(struct jit_frontend *base,
struct jit_block *block,
struct ir *ir) {
@ -95,9 +131,9 @@ static void sh4_frontend_translate_code(struct jit_frontend *base,
while (addr < end) {
uint16_t data = guest->r16(guest->space, addr);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data);
sh4_translate_cb cb = sh4_get_translator(data);
union sh4_instr instr = {data};
cb(guest, ir, flags, addr, instr);
@ -141,50 +177,22 @@ static void sh4_frontend_translate_code(struct jit_frontend *base,
PROF_LEAVE();
}
static void sh4_frontend_dump_code(struct jit_frontend *base, uint32_t addr,
int size) {
static void sh4_frontend_destroy(struct jit_frontend *base) {
struct sh4_frontend *frontend = (struct sh4_frontend *)base;
struct jit_guest *guest = frontend->jit->guest;
char buffer[128];
uint32_t end = addr + size / 2;
while (addr < end) {
uint16_t data = guest->r16(guest->space, addr);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data);
sh4_format(addr, instr, buffer, sizeof(buffer));
LOG_INFO(buffer);
addr += 2;
if (def->flags & SH4_FLAG_DELAYED) {
uint16_t delay_data = guest->r16(guest->space, addr);
union sh4_instr delay_instr = {delay_data};
sh4_format(addr, delay_instr, buffer, sizeof(buffer));
LOG_INFO(buffer);
addr += 2;
}
}
free(frontend);
}
static void sh4_frontend_init(struct jit_frontend *base) {}
void sh4_frontend_destroy(struct sh4_frontend *frontend) {
free(frontend);
}
struct sh4_frontend *sh4_frontend_create(struct jit *jit) {
struct jit_frontend *sh4_frontend_create() {
struct sh4_frontend *frontend = calloc(1, sizeof(struct sh4_frontend));
frontend->jit = jit;
frontend->init = &sh4_frontend_init;
frontend->destroy = &sh4_frontend_destroy;
frontend->translate_code = &sh4_frontend_translate_code;
frontend->dump_code = &sh4_frontend_dump_code;
frontend->lookup_op = &sh4_frontend_lookup_op;
return frontend;
return (struct jit_frontend *)frontend;
}

View File

@ -1,10 +1,7 @@
#ifndef SH4_FRONTEND_H
#define SH4_FRONTEND_H
#include <stdint.h>
struct jit;
struct sh4_frontend;
#include "jit/frontend/jit_frontend.h"
enum {
SH4_FASTMEM = 0x1,
@ -14,7 +11,6 @@ enum {
extern uint32_t sh4_fsca_table[];
struct sh4_frontend *sh4_frontend_create(struct jit *jit);
void sh4_frontend_destroy(struct sh4_frontend *frontend);
struct jit_frontend *sh4_frontend_create();
#endif

View File

@ -363,36 +363,6 @@ void jit_run(struct jit *jit, int32_t cycles) {
jit->backend->run_code(jit->backend, cycles);
}
int jit_init(struct jit *jit, struct jit_guest *guest,
struct jit_frontend *frontend, struct jit_backend *backend) {
jit->guest = guest;
jit->frontend = frontend;
jit->backend = backend;
jit->exc_handler = exception_handler_add(jit, &jit_handle_exception);
jit->lse = lse_create();
jit->cprop = cprop_create();
jit->esimp = esimp_create();
jit->dce = dce_create();
jit->ra = ra_create(jit->backend->registers, jit->backend->num_registers);
/* open perf map if enabled */
if (OPTION_perf) {
#if PLATFORM_DARWIN || PLATFORM_LINUX
char perf_map_path[PATH_MAX];
snprintf(perf_map_path, sizeof(perf_map_path), "/tmp/perf-%d.map",
getpid());
jit->perf_map = fopen(perf_map_path, "a");
CHECK_NOTNULL(jit->perf_map);
#endif
}
jit->frontend->init(jit->frontend);
jit->backend->init(jit->backend);
return 1;
}
void jit_destroy(struct jit *jit) {
if (OPTION_perf) {
if (jit->perf_map) {
@ -427,10 +397,43 @@ void jit_destroy(struct jit *jit) {
free(jit);
}
struct jit *jit_create(const char *tag) {
struct jit *jit_create(const char *tag, struct jit_frontend *frontend,
struct jit_backend *backend, struct jit_guest *guest) {
struct jit *jit = calloc(1, sizeof(struct jit));
strncpy(jit->tag, tag, sizeof(jit->tag));
jit->frontend = frontend;
frontend->jit = jit;
jit->backend = backend;
backend->jit = jit;
jit->guest = guest;
/* setup exception handler to deal with self-modifying code and fastmem
related exceptions */
jit->exc_handler = exception_handler_add(jit, &jit_handle_exception);
jit->lse = lse_create();
jit->cprop = cprop_create();
jit->esimp = esimp_create();
jit->dce = dce_create();
jit->ra = ra_create(jit->backend->registers, jit->backend->num_registers);
/* open perf map if enabled */
if (OPTION_perf) {
#if PLATFORM_DARWIN || PLATFORM_LINUX
char perf_map_path[PATH_MAX];
snprintf(perf_map_path, sizeof(perf_map_path), "/tmp/perf-%d.map",
getpid());
jit->perf_map = fopen(perf_map_path, "a");
CHECK_NOTNULL(jit->perf_map);
#endif
}
jit->frontend->init(jit->frontend);
jit->backend->init(jit->backend);
return jit;
}

View File

@ -91,9 +91,9 @@ struct jit_guest {
struct jit {
char tag[32];
struct jit_guest *guest;
struct jit_frontend *frontend;
struct jit_backend *backend;
struct jit_guest *guest;
struct exception_handler *exc_handler;
/* passes */
@ -121,12 +121,10 @@ struct jit {
int emit_stats;
};
struct jit *jit_create(const char *tag);
struct jit *jit_create(const char *tag, struct jit_frontend *frontend,
struct jit_backend *backend, struct jit_guest *guest);
void jit_destroy(struct jit *jit);
int jit_init(struct jit *jit, struct jit_guest *guest,
struct jit_frontend *frontend, struct jit_backend *backend);
void jit_run(struct jit *jit, int cycles);
void jit_compile_block(struct jit *jit, uint32_t guest_addr);

View File

@ -96,7 +96,8 @@ static void process_file(struct jit *jit, const char *filename,
esimp_run(esimp, &ir);
esimp_destroy(esimp);
} else if (!strcmp(name, "ra")) {
struct ra *ra = ra_create(x64_registers, x64_num_registers);
struct ra *ra =
ra_create(jit->backend->registers, jit->backend->num_registers);
ra_run(ra, &ir);
ra_destroy(ra);
} else {
@ -174,11 +175,6 @@ int main(int argc, char **argv) {
const char *path = argv[1];
/* initailize jit, stubbing out guest interfaces that are used during
assembly to a valid address */
struct jit *jit = jit_create("recc");
jit->emit_stats = 1;
struct jit_guest guest = {0};
guest.r8 = (void *)code;
guest.r16 = (void *)code;
@ -187,9 +183,12 @@ int main(int argc, char **argv) {
guest.w16 = (void *)code;
guest.w32 = (void *)code;
struct x64_backend *backend = x64_backend_create(jit, code, code_size);
struct jit_backend *backend = x64_backend_create(code, code_size);
CHECK(jit_init(jit, &guest, NULL, (struct jit_backend *)backend));
/* initailize jit, stubbing out guest interfaces that are used during
assembly to a valid address */
struct jit *jit = jit_create("recc", NULL, backend, &guest);
jit->emit_stats = 1;
if (fs_isfile(path)) {
process_file(jit, path, 0);
@ -202,7 +201,7 @@ int main(int argc, char **argv) {
pass_stats_dump();
jit_destroy(jit);
x64_backend_destroy(backend);
backend->destroy(backend);
return EXIT_SUCCESS;
}