From 648041696fae4e5d5b31b5739671c7ad84dad10f Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Mon, 7 Aug 2017 22:27:06 -0400 Subject: [PATCH] fixed bitrot in recc removed armv3 software interrupt callback removed circular dependency between jit <-> x64_dispatch --- src/guest/arm7/arm7.c | 106 +++++++++++---------- src/guest/sh4/sh4.c | 111 +++++++++++++--------- src/guest/sh4/sh4.h | 4 +- src/guest/sh4/sh4_ccn.c | 2 +- src/guest/sh4/sh4_dbg.c | 4 +- src/jit/backend/interp/interp_backend.c | 23 +++-- src/jit/backend/interp/interp_backend.h | 6 +- src/jit/backend/x64/x64_backend.cc | 40 ++++---- src/jit/backend/x64/x64_backend.h | 7 +- src/jit/backend/x64/x64_dispatch.cc | 35 +++---- src/jit/backend/x64/x64_emitters.cc | 17 ++-- src/jit/backend/x64/x64_local.h | 2 +- src/jit/frontend/armv3/armv3_disasm.h | 2 +- src/jit/frontend/armv3/armv3_fallback.c | 11 ++- src/jit/frontend/armv3/armv3_frontend.c | 13 ++- src/jit/frontend/armv3/armv3_frontend.h | 6 +- src/jit/frontend/armv3/armv3_guest.h | 19 ++-- src/jit/frontend/sh4/sh4_disasm.h | 2 +- src/jit/frontend/sh4/sh4_frontend.c | 15 ++- src/jit/frontend/sh4/sh4_frontend.h | 6 +- src/jit/frontend/sh4/sh4_guest.h | 11 +-- src/jit/jit.c | 38 +++----- src/jit/jit.h | 46 ++------- src/jit/{backend => }/jit_backend.h | 5 +- src/jit/{frontend => }/jit_frontend.h | 4 +- src/jit/jit_guest.h | 45 +++++++++ src/jit/pass_stats.c | 2 +- src/jit/passes/register_allocation_pass.c | 2 +- tools/recc/main.c | 65 +++++-------- tools/retrace/depth.c | 2 +- 30 files changed, 329 insertions(+), 322 deletions(-) rename src/jit/{backend => }/jit_backend.h (97%) rename src/jit/{frontend => }/jit_frontend.h (91%) create mode 100644 src/jit/jit_guest.h diff --git a/src/guest/arm7/arm7.c b/src/guest/arm7/arm7.c index 10804516..4020b6e4 100644 --- a/src/guest/arm7/arm7.c +++ b/src/guest/arm7/arm7.c @@ -26,7 +26,7 @@ struct arm7 { /* jit */ struct jit *jit; - struct armv3_guest *guest; + struct jit_guest *guest; struct jit_frontend *frontend; struct jit_backend *backend; @@ -92,17 +92,6 @@ static void arm7_restore_mode(void *data) { arm7_update_pending_interrupts(arm); } -static void arm7_software_interrupt(void *data) { - struct arm7 *arm = data; - - uint32_t newsr = (arm->ctx.r[CPSR] & ~M_MASK); - newsr |= I_MASK | MODE_SVC; - - arm7_switch_mode(arm, newsr); - arm->ctx.r[14] = arm->ctx.r[15] + 4; - arm->ctx.r[15] = 0x08; -} - static void arm7_update_pending_interrupts(struct arm7 *arm) { uint32_t interrupt_mask = 0; @@ -113,7 +102,7 @@ static void arm7_update_pending_interrupts(struct arm7 *arm) { arm->ctx.pending_interrupts = arm->requested_interrupts & interrupt_mask; } -void arm7_check_pending_interrupts(void *data) { +static void arm7_check_interrupts(void *data) { struct arm7 *arm = data; if (!arm->ctx.pending_interrupts) { @@ -132,6 +121,14 @@ void arm7_check_pending_interrupts(void *data) { } } +static void arm7_link_code(struct arm7 *arm, void *branch, uint32_t target) { + jit_link_code(arm->jit, branch, target); +} + +static void arm7_compile_code(struct arm7 *arm, uint32_t addr) { + jit_compile_code(arm->jit, addr); +} + void arm7_raise_interrupt(struct arm7 *arm, enum arm7_interrupt intr) { arm->requested_interrupts |= intr; arm7_update_pending_interrupts(arm); @@ -140,7 +137,7 @@ void arm7_raise_interrupt(struct arm7 *arm, enum arm7_interrupt intr) { void arm7_reset(struct arm7 *arm) { LOG_INFO("arm7_reset"); - jit_free_blocks(arm->jit); + jit_free_code(arm->jit); /* reset context */ memset(&arm->ctx, 0, sizeof(arm->ctx)); @@ -174,49 +171,58 @@ static void arm7_run(struct device *dev, int64_t ns) { PROF_LEAVE(); } +static void arm7_guest_destroy(struct jit_guest *guest) { + free((struct armv3_guest *)guest); +} + +static struct jit_guest *arm7_guest_create(struct arm7 *arm) { + struct armv3_guest *guest = calloc(1, sizeof(struct armv3_guest)); + + /* dispatch cache */ + guest->addr_mask = 0x001ffffc; + + /* memory interface */ + guest->ctx = &arm->ctx; + guest->mem = as_translate(arm->memory_if->space, 0x0); + guest->space = arm->memory_if->space; + guest->lookup = &as_lookup; + guest->r8 = &as_read8; + guest->r16 = &as_read16; + guest->r32 = &as_read32; + guest->w8 = &as_write8; + guest->w16 = &as_write16; + guest->w32 = &as_write32; + + /* runtime interface */ + guest->data = arm; + guest->offset_pc = (int)offsetof(struct armv3_context, r[15]); + guest->offset_cycles = (int)offsetof(struct armv3_context, run_cycles); + guest->offset_instrs = (int)offsetof(struct armv3_context, ran_instrs); + guest->offset_interrupts = + (int)offsetof(struct armv3_context, pending_interrupts); + guest->compile_code = (jit_compile_cb)&arm7_compile_code; + guest->link_code = (jit_link_cb)&arm7_link_code; + guest->check_interrupts = (jit_interrupt_cb)&arm7_check_interrupts; + guest->switch_mode = (armv3_switch_mode_cb)&arm7_switch_mode; + guest->restore_mode = (armv3_restore_mode_cb)&arm7_restore_mode; + + return (struct jit_guest *)guest; +} + static int arm7_init(struct device *dev) { struct arm7 *arm = (struct arm7 *)dev; struct dreamcast *dc = arm->dc; - /* initialize jit and its interfaces */ - arm->frontend = armv3_frontend_create(); - + /* initialize jit */ + arm->guest = arm7_guest_create(arm); + arm->frontend = armv3_frontend_create(arm->guest); #if ARCH_X64 DEFINE_JIT_CODE_BUFFER(arm7_code); - arm->backend = x64_backend_create(arm7_code, sizeof(arm7_code)); + arm->backend = x64_backend_create(arm->guest, arm7_code, sizeof(arm7_code)); #else - arm->backend = interp_backend_create(); + arm->backend = interp_backend_create(arm->guest, arm->frontend); #endif - - { - arm->guest = armv3_guest_create(); - - arm->guest->addr_mask = 0x001ffffc; - arm->guest->offset_pc = (int)offsetof(struct armv3_context, r[15]); - arm->guest->offset_cycles = (int)offsetof(struct armv3_context, run_cycles); - arm->guest->offset_instrs = (int)offsetof(struct armv3_context, ran_instrs); - arm->guest->offset_interrupts = - (int)offsetof(struct armv3_context, pending_interrupts); - arm->guest->data = arm; - arm->guest->check_interrupts = &arm7_check_pending_interrupts; - - arm->guest->ctx = &arm->ctx; - arm->guest->mem = as_translate(arm->memory_if->space, 0x0); - arm->guest->space = arm->memory_if->space; - arm->guest->switch_mode = &arm7_switch_mode; - arm->guest->restore_mode = &arm7_restore_mode; - arm->guest->software_interrupt = &arm7_software_interrupt; - arm->guest->lookup = &as_lookup; - arm->guest->r8 = &as_read8; - arm->guest->r16 = &as_read16; - arm->guest->r32 = &as_read32; - arm->guest->w8 = &as_write8; - arm->guest->w16 = &as_write16; - arm->guest->w32 = &as_write32; - } - - arm->jit = jit_create("arm7", arm->frontend, arm->backend, - (struct jit_guest *)arm->guest); + arm->jit = jit_create("arm7", arm->frontend, arm->backend); arm->wave_ram = memory_translate(dc->memory, "aica wave ram", 0x0); @@ -225,7 +231,7 @@ static int arm7_init(struct device *dev) { void arm7_destroy(struct arm7 *arm) { jit_destroy(arm->jit); - armv3_guest_destroy(arm->guest); + arm7_guest_destroy(arm->guest); arm->frontend->destroy(arm->frontend); arm->backend->destroy(arm->backend); diff --git a/src/guest/sh4/sh4.c b/src/guest/sh4/sh4.c index 832dbc1c..f196eebd 100644 --- a/src/guest/sh4/sh4.c +++ b/src/guest/sh4/sh4.c @@ -153,6 +153,14 @@ static void sh4_check_interrupts(struct sh4 *sh4) { sh4_sr_updated(sh4, sh4->ctx.ssr); } +static void sh4_link_code(struct sh4 *sh4, void *branch, uint32_t target) { + jit_link_code(sh4->jit, branch, target); +} + +static void sh4_compile_code(struct sh4 *sh4, uint32_t addr) { + jit_compile_code(sh4->jit, addr); +} + static void sh4_invalid_instr(struct sh4 *sh4) { sh4_exception(sh4, SH4_EXC_ILLINSTR); } @@ -174,53 +182,62 @@ static void sh4_run(struct device *dev, int64_t ns) { PROF_LEAVE(); } +static void sh4_guest_destroy(struct jit_guest *guest) { + free((struct sh4_guest *)guest); +} + +static struct jit_guest *sh4_guest_create(struct sh4 *sh4) { + struct sh4_guest *guest = calloc(1, sizeof(struct sh4_guest)); + + /* dispatch cache */ + guest->addr_mask = 0x00fffffe; + + /* memory interface */ + guest->ctx = &sh4->ctx; + guest->mem = as_translate(sh4->memory_if->space, 0x0); + guest->space = sh4->memory_if->space; + guest->lookup = &as_lookup; + guest->r8 = &as_read8; + guest->r16 = &as_read16; + guest->r32 = &as_read32; + guest->w8 = &as_write8; + guest->w16 = &as_write16; + guest->w32 = &as_write32; + + /* runtime interface */ + guest->data = sh4; + guest->offset_pc = (int)offsetof(struct sh4_context, pc); + guest->offset_cycles = (int)offsetof(struct sh4_context, run_cycles); + guest->offset_instrs = (int)offsetof(struct sh4_context, ran_instrs); + guest->offset_interrupts = + (int)offsetof(struct sh4_context, pending_interrupts); + guest->compile_code = (jit_compile_cb)&sh4_compile_code; + guest->link_code = (jit_link_cb)&sh4_link_code; + guest->check_interrupts = (jit_interrupt_cb)&sh4_check_interrupts; + guest->invalid_instr = (sh4_invalid_instr_cb)&sh4_invalid_instr; + guest->ltlb = (sh4_ltlb_cb)&sh4_mmu_ltlb; + guest->pref = (sh4_pref_cb)&sh4_ccn_pref; + guest->sleep = (sh4_sleep_cb)&sh4_sleep; + guest->sr_updated = (sh4_sr_updated_cb)&sh4_sr_updated; + guest->fpscr_updated = (sh4_fpscr_updated_cb)&sh4_fpscr_updated; + + return (struct jit_guest *)guest; +} + static int sh4_init(struct device *dev) { struct sh4 *sh4 = (struct sh4 *)dev; struct dreamcast *dc = sh4->dc; - /* initialize jit and its interfaces */ - sh4->frontend = sh4_frontend_create(); - + /* initialize jit */ + sh4->guest = sh4_guest_create(sh4); + sh4->frontend = sh4_frontend_create(sh4->guest); #if ARCH_X64 DEFINE_JIT_CODE_BUFFER(sh4_code); - sh4->backend = x64_backend_create(sh4_code, sizeof(sh4_code)); + sh4->backend = x64_backend_create(sh4->guest, sh4_code, sizeof(sh4_code)); #else - sh4->backend = interp_backend_create(); + sh4->backend = interp_backend_create(sh4->guest, sh4->frontend); #endif - - { - sh4->guest = sh4_guest_create(); - - sh4->guest->addr_mask = 0x00fffffe; - - sh4->guest->data = sh4; - sh4->guest->offset_pc = (int)offsetof(struct sh4_context, pc); - sh4->guest->offset_cycles = (int)offsetof(struct sh4_context, run_cycles); - sh4->guest->offset_instrs = (int)offsetof(struct sh4_context, ran_instrs); - sh4->guest->offset_interrupts = - (int)offsetof(struct sh4_context, pending_interrupts); - sh4->guest->check_interrupts = (jit_interrupt_cb)&sh4_check_interrupts; - - sh4->guest->ctx = &sh4->ctx; - sh4->guest->mem = as_translate(sh4->memory_if->space, 0x0); - sh4->guest->space = sh4->memory_if->space; - sh4->guest->invalid_instr = (sh4_invalid_instr_cb)&sh4_invalid_instr; - sh4->guest->ltlb = (sh4_ltlb_cb)&sh4_mmu_ltlb; - sh4->guest->pref = (sh4_pref_cb)&sh4_ccn_pref; - sh4->guest->sleep = (sh4_sleep_cb)&sh4_sleep; - sh4->guest->sr_updated = (sh4_sr_updated_cb)&sh4_sr_updated; - sh4->guest->fpscr_updated = (sh4_fpscr_updated_cb)&sh4_fpscr_updated; - sh4->guest->lookup = &as_lookup; - sh4->guest->r8 = &as_read8; - sh4->guest->r16 = &as_read16; - sh4->guest->r32 = &as_read32; - sh4->guest->w8 = &as_write8; - sh4->guest->w16 = &as_write16; - sh4->guest->w32 = &as_write32; - } - - sh4->jit = jit_create("sh4", sh4->frontend, sh4->backend, - (struct jit_guest *)sh4->guest); + sh4->jit = jit_create("sh4", sh4->frontend, sh4->backend); return 1; } @@ -242,7 +259,7 @@ void sh4_set_exception_handler(struct sh4 *sh4, } void sh4_reset(struct sh4 *sh4, uint32_t pc) { - jit_free_blocks(sh4->jit); + jit_free_code(sh4->jit); /* reset context */ memset(&sh4->ctx, 0, sizeof(sh4->ctx)); @@ -276,17 +293,17 @@ void sh4_debug_menu(struct sh4 *sh4) { if (igBeginMainMenuBar()) { if (igBeginMenu("SH4", 1)) { if (igMenuItem("clear cache", NULL, 0, 1)) { - jit_invalidate_blocks(sh4->jit); + jit_invalidate_code(sh4->jit); } - if (!jit->dump_blocks) { - if (igMenuItem("start dumping blocks", NULL, 0, 1)) { - jit->dump_blocks = 1; - jit_invalidate_blocks(jit); + if (!jit->dump_code) { + if (igMenuItem("start dumping code", NULL, 0, 1)) { + jit->dump_code = 1; + jit_invalidate_code(jit); } } else { - if (igMenuItem("stop dumping blocks", NULL, 1, 1)) { - jit->dump_blocks = 0; + if (igMenuItem("stop dumping code", NULL, 1, 1)) { + jit->dump_code = 0; } } diff --git a/src/guest/sh4/sh4.h b/src/guest/sh4/sh4.h index 4b7e32e3..686f00b3 100644 --- a/src/guest/sh4/sh4.h +++ b/src/guest/sh4/sh4.h @@ -12,7 +12,7 @@ struct dreamcast; struct jit; struct jit_backend; struct jit_frontend; -struct sh4_guest; +struct jit_guest; #define SH4_CLOCK_FREQ INT64_C(200000000) @@ -58,7 +58,7 @@ struct sh4 { /* jit */ struct jit *jit; - struct sh4_guest *guest; + struct jit_guest *guest; struct jit_frontend *frontend; struct jit_backend *backend; diff --git a/src/guest/sh4/sh4_ccn.c b/src/guest/sh4/sh4_ccn.c index 1bff6000..5689316f 100644 --- a/src/guest/sh4/sh4_ccn.c +++ b/src/guest/sh4/sh4_ccn.c @@ -25,7 +25,7 @@ static void sh4_ccn_reset(struct sh4 *sh4) { end the block */ LOG_INFO("sh4_ccn_reset"); - jit_invalidate_blocks(sh4->jit); + jit_invalidate_code(sh4->jit); } void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) { diff --git a/src/guest/sh4/sh4_dbg.c b/src/guest/sh4/sh4_dbg.c index 9f15cfe4..6516d07f 100644 --- a/src/guest/sh4/sh4_dbg.c +++ b/src/guest/sh4/sh4_dbg.c @@ -111,7 +111,7 @@ void sh4_dbg_remove_breakpoint(struct device *dev, int type, uint32_t addr) { as_write16(sh4->memory_if->space, addr, bp->instr); /* free code cache to remove block containing the invalid instruction */ - jit_free_blocks(sh4->jit); + jit_free_code(sh4->jit); destroy_breakpoint(sh4, bp); } @@ -126,7 +126,7 @@ void sh4_dbg_add_breakpoint(struct device *dev, int type, uint32_t addr) { as_write16(sh4->memory_if->space, addr, 0); /* free code cache to remove block containing the original instruction */ - jit_free_blocks(sh4->jit); + jit_free_code(sh4->jit); } void sh4_dbg_step(struct device *dev) { diff --git a/src/jit/backend/interp/interp_backend.c b/src/jit/backend/interp/interp_backend.c index f8ab2935..d7bb4928 100644 --- a/src/jit/backend/interp/interp_backend.c +++ b/src/jit/backend/interp/interp_backend.c @@ -1,16 +1,20 @@ #include -#include "jit/backend/jit_backend.h" -#include "jit/frontend/jit_frontend.h" #include "jit/jit.h" +#include "jit/jit_backend.h" +#include "jit/jit_frontend.h" +#include "jit/jit_guest.h" struct interp_backend { struct jit_backend; + + /* used to resolve the fallback handler for each instruction */ + struct jit_frontend *frontend; }; 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; + struct jit_frontend *frontend = backend->frontend; + struct jit_guest *guest = backend->guest; uint8_t *ctx = guest->ctx; uint32_t *pc = (uint32_t *)(ctx + guest->offset_pc); int32_t *run_cycles = (int32_t *)(ctx + guest->offset_cycles); @@ -27,8 +31,7 @@ static void interp_backend_run_code(struct jit_backend *base, int cycles) { 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); + const struct jit_opdef *def = frontend->lookup_op(frontend, &data); def->fallback(guest, addr, data); cycles += def->cycles; instrs += 1; @@ -57,14 +60,10 @@ static void interp_backend_destroy(struct jit_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 jit_backend *interp_backend_create(struct jit_frontend *frontend) { struct interp_backend *backend = calloc(1, sizeof(struct interp_backend)); - backend->init = &interp_backend_init; + backend->frontend = frontend; backend->destroy = &interp_backend_destroy; /* compile interface */ diff --git a/src/jit/backend/interp/interp_backend.h b/src/jit/backend/interp/interp_backend.h index 046b0ad0..dc5ab15e 100644 --- a/src/jit/backend/interp/interp_backend.h +++ b/src/jit/backend/interp/interp_backend.h @@ -1,8 +1,10 @@ #ifndef INTERP_BACKEND_H #define INTERP_BACKEND_H -#include "jit/backend/jit_backend.h" +#include "jit/jit_backend.h" -struct jit_backend *interp_backend_create(); +struct jit_frontend; + +struct jit_backend *interp_backend_create(struct jit_frontend *frontend); #endif diff --git a/src/jit/backend/x64/x64_backend.cc b/src/jit/backend/x64/x64_backend.cc index 4fac6451..4d31db89 100644 --- a/src/jit/backend/x64/x64_backend.cc +++ b/src/jit/backend/x64/x64_backend.cc @@ -4,11 +4,12 @@ extern "C" { #include "core/exception_handler.h" #include "core/memory.h" #include "core/profiler.h" -#include "jit/backend/jit_backend.h" #include "jit/backend/x64/x64_backend.h" #include "jit/backend/x64/x64_disassembler.h" #include "jit/ir/ir.h" #include "jit/jit.h" +#include "jit/jit_backend.h" +#include "jit/jit_guest.h" } /* @@ -309,8 +310,7 @@ static void x64_backend_emit_epilogue(struct x64_backend *backend, static void x64_backend_emit_prologue(struct x64_backend *backend, struct jit_block *block) { - struct jit *jit = backend->base.jit; - struct jit_guest *guest = jit->guest; + struct jit_guest *guest = backend->base.guest; auto &e = *backend->codegen; @@ -479,7 +479,7 @@ static void x64_backend_emit_constants(struct x64_backend *backend) { static int x64_backend_handle_exception(struct jit_backend *base, struct exception_state *ex) { struct x64_backend *backend = container_of(base, struct x64_backend, base); - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; const uint8_t *data = (const uint8_t *)ex->thread_state.rip; @@ -631,27 +631,13 @@ static void x64_backend_destroy(struct jit_backend *base) { free(backend); } -static void x64_backend_init(struct jit_backend *base) { - struct x64_backend *backend = container_of(base, struct x64_backend, base); - - x64_dispatch_init(backend); - - /* emit thunks into a fixed amount of space to speed up resets */ - x64_dispatch_emit_thunks(backend); - x64_backend_emit_thunks(backend); - x64_backend_emit_constants(backend); - CHECK_LT(backend->codegen->getSize(), X64_THUNK_SIZE); -} - -struct jit_backend *x64_backend_create(void *code, int code_size) { +struct jit_backend *x64_backend_create(struct jit_guest *guest, void *code, + int code_size) { struct x64_backend *backend = (struct x64_backend *)calloc(1, sizeof(struct x64_backend)); Xbyak::util::Cpu cpu; - int r = protect_pages(code, code_size, ACC_READWRITEEXEC); - CHECK(r); - - backend->base.init = &x64_backend_init; + backend->base.guest = guest; backend->base.destroy = &x64_backend_destroy; /* compile interface */ @@ -672,11 +658,23 @@ struct jit_backend *x64_backend_create(void *code, int code_size) { backend->base.patch_edge = &x64_dispatch_patch_edge; backend->base.restore_edge = &x64_dispatch_restore_edge; + /* setup codegen buffer */ + int r = protect_pages(code, code_size, ACC_READWRITEEXEC); + CHECK(r); + backend->codegen = new Xbyak::CodeGenerator(code_size, code); backend->use_avx = cpu.has(Xbyak::util::Cpu::tAVX2); + /* create disassembler */ int res = cs_open(CS_ARCH_X86, CS_MODE_64, &backend->capstone_handle); CHECK_EQ(res, CS_ERR_OK); + /* emit initial thunks */ + x64_dispatch_init(backend); + x64_dispatch_emit_thunks(backend); + x64_backend_emit_thunks(backend); + x64_backend_emit_constants(backend); + CHECK_LT(backend->codegen->getSize(), X64_THUNK_SIZE); + return &backend->base; } diff --git a/src/jit/backend/x64/x64_backend.h b/src/jit/backend/x64/x64_backend.h index 6cc29279..94c7d51b 100644 --- a/src/jit/backend/x64/x64_backend.h +++ b/src/jit/backend/x64/x64_backend.h @@ -1,8 +1,11 @@ #ifndef X64_BACKEND_H #define X64_BACKEND_H -#include "jit/backend/jit_backend.h" +#include "jit/jit_backend.h" -struct jit_backend *x64_backend_create(void *code, int code_size); +struct jit_guest; + +struct jit_backend *x64_backend_create(struct jit_guest *guest, void *code, + int code_size); #endif diff --git a/src/jit/backend/x64/x64_dispatch.cc b/src/jit/backend/x64/x64_dispatch.cc index ac6a4e05..6a79b711 100644 --- a/src/jit/backend/x64/x64_dispatch.cc +++ b/src/jit/backend/x64/x64_dispatch.cc @@ -4,6 +4,7 @@ extern "C" { #include "core/assert.h" #include "core/profiler.h" #include "jit/jit.h" +#include "jit/jit_guest.h" } DEFINE_COUNTER(edges_patched); @@ -79,7 +80,7 @@ void x64_dispatch_run_code(struct jit_backend *base, int cycles) { } void x64_dispatch_emit_thunks(struct x64_backend *backend) { - struct jit *jit = backend->base.jit; + struct jit_guest *guest = backend->base.guest; auto &e = *backend->codegen; @@ -98,7 +99,7 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) { /* invasively look into the jit's cache */ e.mov(e.rax, (uint64_t)backend->cache); - e.mov(e.ecx, e.dword[guestctx + jit->guest->offset_pc]); + e.mov(e.ecx, e.dword[guestctx + guest->offset_pc]); e.and_(e.ecx, backend->cache_mask); e.jmp(e.qword[e.rax + e.rcx * (sizeof(void *) >> backend->cache_shift)]); } @@ -115,11 +116,11 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) { backend->dispatch_static = e.getCurr(); #if LINK_STATIC_BRANCHES - e.mov(arg0, (uint64_t)jit); + e.mov(arg0, (uint64_t)guest->data); e.pop(arg1); e.sub(arg1, 5 /* sizeof jmp instr */); - e.mov(arg2, e.qword[guestctx + jit->guest->offset_pc]); - e.call(&jit_add_edge); + e.mov(arg2, e.qword[guestctx + guest->offset_pc]); + e.call(guest->link_code); #else e.pop(arg1); #endif @@ -133,9 +134,9 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) { backend->dispatch_compile = e.getCurr(); - e.mov(arg0, (uint64_t)jit); - e.mov(arg1, e.dword[guestctx + jit->guest->offset_pc]); - e.call(&jit_compile_block); + e.mov(arg0, (uint64_t)guest->data); + e.mov(arg1, e.dword[guestctx + guest->offset_pc]); + e.call(guest->compile_code); e.jmp(backend->dispatch_dynamic); } @@ -146,8 +147,8 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) { backend->dispatch_interrupt = e.getCurr(); - e.mov(arg0, (uint64_t)jit->guest->data); - e.call(jit->guest->check_interrupts); + e.mov(arg0, (uint64_t)guest->data); + e.call(guest->check_interrupts); e.jmp(backend->dispatch_dynamic); } @@ -173,12 +174,12 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) { e.sub(e.rsp, X64_STACK_SIZE + 8); /* assign fixed registers */ - e.mov(guestctx, (uint64_t)jit->guest->ctx); - e.mov(guestmem, (uint64_t)jit->guest->mem); + e.mov(guestctx, (uint64_t)guest->ctx); + e.mov(guestmem, (uint64_t)guest->mem); /* reset run state */ - e.mov(e.dword[guestctx + jit->guest->offset_cycles], arg0); - e.mov(e.dword[guestctx + jit->guest->offset_instrs], 0); + e.mov(e.dword[guestctx + guest->offset_cycles], arg0); + e.mov(e.dword[guestctx + guest->offset_instrs], 0); e.jmp(backend->dispatch_dynamic); } @@ -216,11 +217,11 @@ void x64_dispatch_shutdown(struct x64_backend *backend) { } void x64_dispatch_init(struct x64_backend *backend) { - struct jit *jit = backend->base.jit; + struct jit_guest *guest = backend->base.guest; /* initialize code cache, one entry per possible block begin */ - backend->cache_mask = jit->guest->addr_mask; - backend->cache_shift = ctz32(jit->guest->addr_mask); + backend->cache_mask = guest->addr_mask; + backend->cache_shift = ctz32(guest->addr_mask); backend->cache_size = (backend->cache_mask >> backend->cache_shift) + 1; backend->cache = (void **)malloc(backend->cache_size * sizeof(void *)); } diff --git a/src/jit/backend/x64/x64_emitters.cc b/src/jit/backend/x64/x64_emitters.cc index cb3ebcff..d1721dcc 100644 --- a/src/jit/backend/x64/x64_emitters.cc +++ b/src/jit/backend/x64/x64_emitters.cc @@ -3,6 +3,7 @@ extern "C" { #include "jit/ir/ir.h" #include "jit/jit.h" +#include "jit/jit_guest.h" } #define EMITTER(op, constraints) \ @@ -62,11 +63,13 @@ struct jit_emitter x64_emitters[IR_NUM_OPS]; EMITTER(SOURCE_INFO, CONSTRAINTS(NONE, IMM_I32, IMM_I32)) { /*uint32_t addr = ARG0->i32;*/ int index = ARG1->i32; - block->source_map[index] = e.getCurr(); + if (block->source_map) { + block->source_map[index] = e.getCurr(); + } } EMITTER(FALLBACK, CONSTRAINTS(NONE, IMM_I64, IMM_I32, IMM_I32)) { - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; void *fallback = (void *)ARG0->i64; uint32_t addr = ARG1->i32; uint32_t raw_instr = ARG2->i32; @@ -92,7 +95,7 @@ EMITTER(STORE_HOST, CONSTRAINTS(NONE, REG_I64, VAL_ALL)) { } EMITTER(LOAD_GUEST, CONSTRAINTS(REG_ALL, REG_I64 | IMM_I32)) { - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; Xbyak::Reg dst = RES_REG; struct ir_value *addr = ARG0; @@ -149,7 +152,7 @@ EMITTER(LOAD_GUEST, CONSTRAINTS(REG_ALL, REG_I64 | IMM_I32)) { } EMITTER(STORE_GUEST, CONSTRAINTS(NONE, REG_I64 | IMM_I32, VAL_ALL)) { - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; struct ir_value *addr = ARG0; struct ir_value *data = ARG1; @@ -903,7 +906,7 @@ EMITTER(LSHD, CONSTRAINTS(REG_ARG0, REG_I64, REG_I64)) { } EMITTER(BRANCH, CONSTRAINTS(NONE, REG_I64 | IMM_I32)) { - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; if (ir_is_constant(ARG0)) { uint32_t addr = ARG0->i32; @@ -917,7 +920,7 @@ EMITTER(BRANCH, CONSTRAINTS(NONE, REG_I64 | IMM_I32)) { } EMITTER(BRANCH_FALSE, CONSTRAINTS(NONE, REG_I64 | IMM_I32, REG_I64)) { - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; Xbyak::Reg cond = ARG1_REG; Xbyak::Label next; @@ -938,7 +941,7 @@ EMITTER(BRANCH_FALSE, CONSTRAINTS(NONE, REG_I64 | IMM_I32, REG_I64)) { } EMITTER(BRANCH_TRUE, CONSTRAINTS(NONE, REG_I64 | IMM_I32, REG_I64)) { - struct jit_guest *guest = backend->base.jit->guest; + struct jit_guest *guest = backend->base.guest; Xbyak::Reg cond = ARG1_REG; Xbyak::Label next; diff --git a/src/jit/backend/x64/x64_local.h b/src/jit/backend/x64/x64_local.h index ce862939..8f6159e9 100644 --- a/src/jit/backend/x64/x64_local.h +++ b/src/jit/backend/x64/x64_local.h @@ -9,7 +9,7 @@ #include extern "C" { -#include "jit/backend/jit_backend.h" +#include "jit/jit_backend.h" } enum xmm_constant { diff --git a/src/jit/frontend/armv3/armv3_disasm.h b/src/jit/frontend/armv3/armv3_disasm.h index 85c49673..474b2c95 100644 --- a/src/jit/frontend/armv3/armv3_disasm.h +++ b/src/jit/frontend/armv3/armv3_disasm.h @@ -2,7 +2,7 @@ #define ARMV3_DISASM_H #include -#include "jit/frontend/jit_frontend.h" +#include "jit/jit_frontend.h" enum armv3_op_flag { FLAG_SET_PC = 0x1, diff --git a/src/jit/frontend/armv3/armv3_fallback.c b/src/jit/frontend/armv3/armv3_fallback.c index 70ca160c..8f2b8e10 100644 --- a/src/jit/frontend/armv3/armv3_fallback.c +++ b/src/jit/frontend/armv3/armv3_fallback.c @@ -781,10 +781,15 @@ FALLBACK(SWP) { /* * software interrupt */ - FALLBACK(SWI) { CHECK_COND(); - REG(15) = addr + 4; - guest->software_interrupt(guest->data); + uint32_t oldsr = REG(CPSR); + uint32_t newsr = (oldsr & ~M_MASK) | I_MASK | MODE_SVC; + + guest->switch_mode(guest->data, newsr); + REG(14) = addr + 4; + REG(15) = 0x8; + + LOG_WARNING("SWI"); } diff --git a/src/jit/frontend/armv3/armv3_frontend.c b/src/jit/frontend/armv3/armv3_frontend.c index 502808ea..98cbbb85 100644 --- a/src/jit/frontend/armv3/armv3_frontend.c +++ b/src/jit/frontend/armv3/armv3_frontend.c @@ -5,6 +5,7 @@ #include "jit/frontend/armv3/armv3_guest.h" #include "jit/ir/ir.h" #include "jit/jit.h" +#include "jit/jit_guest.h" struct armv3_frontend { struct jit_frontend; @@ -18,7 +19,7 @@ static const struct jit_opdef *armv3_frontend_lookup_op( static void armv3_frontend_dump_code(struct jit_frontend *base, const struct jit_block *block) { struct armv3_frontend *frontend = (struct armv3_frontend *)base; - struct jit_guest *guest = frontend->jit->guest; + struct jit_guest *guest = frontend->guest; char buffer[128]; @@ -37,7 +38,7 @@ 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; + struct armv3_guest *guest = (struct armv3_guest *)frontend->guest; for (int offset = 0; offset < block->guest_size; offset += 4) { uint32_t addr = block->guest_addr + offset; @@ -52,7 +53,7 @@ static void armv3_frontend_translate_code(struct jit_frontend *base, static void armv3_frontend_analyze_code(struct jit_frontend *base, struct jit_block *block) { struct armv3_frontend *frontend = (struct armv3_frontend *)base; - struct armv3_guest *guest = (struct armv3_guest *)frontend->jit->guest; + struct armv3_guest *guest = (struct armv3_guest *)frontend->guest; uint32_t addr = block->guest_addr; block->guest_size = 0; @@ -91,12 +92,10 @@ void armv3_frontend_destroy(struct jit_frontend *base) { free(frontend); } -static void armv3_frontend_init(struct jit_frontend *frontend) {} - -struct jit_frontend *armv3_frontend_create() { +struct jit_frontend *armv3_frontend_create(struct jit_guest *guest) { struct armv3_frontend *frontend = calloc(1, sizeof(struct armv3_frontend)); - frontend->init = &armv3_frontend_init; + frontend->guest = guest; frontend->destroy = &armv3_frontend_destroy; frontend->analyze_code = &armv3_frontend_analyze_code; frontend->translate_code = &armv3_frontend_translate_code; diff --git a/src/jit/frontend/armv3/armv3_frontend.h b/src/jit/frontend/armv3/armv3_frontend.h index fdf94b21..dd9b6f87 100644 --- a/src/jit/frontend/armv3/armv3_frontend.h +++ b/src/jit/frontend/armv3/armv3_frontend.h @@ -1,12 +1,14 @@ #ifndef ARMV3_FRONTEND_H #define ARMV3_FRONTEND_H -#include "jit/frontend/jit_frontend.h" +#include "jit/jit_frontend.h" + +struct jit_guest; enum armv3_block_flags { PC_SET = 0x1, }; -struct jit_frontend *armv3_frontend_create(); +struct jit_frontend *armv3_frontend_create(struct jit_guest *guest); #endif diff --git a/src/jit/frontend/armv3/armv3_guest.h b/src/jit/frontend/armv3/armv3_guest.h index 9a0b4275..b8eb8e6d 100644 --- a/src/jit/frontend/armv3/armv3_guest.h +++ b/src/jit/frontend/armv3/armv3_guest.h @@ -1,23 +1,18 @@ #ifndef ARMV3_GUEST_H #define ARMV3_GUEST_H -#include "jit/jit.h" +#include +#include "jit/jit_guest.h" + +typedef void (*armv3_switch_mode_cb)(void *, uint32_t); +typedef void (*armv3_restore_mode_cb)(void *); struct armv3_guest { struct jit_guest; /* runtime interface */ - void (*switch_mode)(void *, uint32_t); - void (*restore_mode)(void *); - void (*software_interrupt)(void *); + armv3_switch_mode_cb switch_mode; + armv3_restore_mode_cb restore_mode; }; -static inline struct armv3_guest *armv3_guest_create() { - return calloc(1, sizeof(struct armv3_guest)); -} - -static inline void armv3_guest_destroy(struct armv3_guest *guest) { - free(guest); -} - #endif diff --git a/src/jit/frontend/sh4/sh4_disasm.h b/src/jit/frontend/sh4/sh4_disasm.h index 14d49a60..b7dc305b 100644 --- a/src/jit/frontend/sh4/sh4_disasm.h +++ b/src/jit/frontend/sh4/sh4_disasm.h @@ -2,7 +2,7 @@ #define SH4_DISASM_H #include -#include "jit/frontend/jit_frontend.h" +#include "jit/jit_frontend.h" enum { SH4_FLAG_INVALID = 0x1, diff --git a/src/jit/frontend/sh4/sh4_frontend.c b/src/jit/frontend/sh4/sh4_frontend.c index c922eaff..b6fab650 100644 --- a/src/jit/frontend/sh4/sh4_frontend.c +++ b/src/jit/frontend/sh4/sh4_frontend.c @@ -1,12 +1,13 @@ #include "jit/frontend/sh4/sh4_frontend.h" #include "core/profiler.h" -#include "jit/frontend/jit_frontend.h" #include "jit/frontend/sh4/sh4_disasm.h" #include "jit/frontend/sh4/sh4_fallback.h" #include "jit/frontend/sh4/sh4_guest.h" #include "jit/frontend/sh4/sh4_translate.h" #include "jit/ir/ir.h" #include "jit/jit.h" +#include "jit/jit_frontend.h" +#include "jit/jit_guest.h" /* * fsca estimate lookup table, used by the jit and interpreter @@ -27,7 +28,7 @@ static const struct jit_opdef *sh4_frontend_lookup_op(struct jit_frontend *base, static void sh4_frontend_dump_code(struct jit_frontend *base, const struct jit_block *block) { struct sh4_frontend *frontend = (struct sh4_frontend *)base; - struct jit_guest *guest = frontend->jit->guest; + struct jit_guest *guest = frontend->guest; char buffer[128]; @@ -61,7 +62,7 @@ static void sh4_frontend_translate_code(struct jit_frontend *base, struct jit_block *block, struct ir *ir) { struct sh4_frontend *frontend = (struct sh4_frontend *)base; - struct sh4_guest *guest = (struct sh4_guest *)frontend->jit->guest; + struct sh4_guest *guest = (struct sh4_guest *)frontend->guest; struct sh4_context *ctx = (struct sh4_context *)guest->ctx; PROF_ENTER("cpu", "sh4_frontend_translate_code"); @@ -156,7 +157,7 @@ static void sh4_frontend_translate_code(struct jit_frontend *base, static void sh4_frontend_analyze_code(struct jit_frontend *base, struct jit_block *block) { struct sh4_frontend *frontend = (struct sh4_frontend *)base; - struct sh4_guest *guest = (struct sh4_guest *)frontend->jit->guest; + struct sh4_guest *guest = (struct sh4_guest *)frontend->guest; static int IDLE_MASK = SH4_FLAG_LOAD | SH4_FLAG_COND | SH4_FLAG_CMP; int idle_loop = 1; @@ -294,12 +295,10 @@ static void sh4_frontend_destroy(struct jit_frontend *base) { free(frontend); } -static void sh4_frontend_init(struct jit_frontend *base) {} - -struct jit_frontend *sh4_frontend_create() { +struct jit_frontend *sh4_frontend_create(struct jit_guest *guest) { struct sh4_frontend *frontend = calloc(1, sizeof(struct sh4_frontend)); - frontend->init = &sh4_frontend_init; + frontend->guest = guest; frontend->destroy = &sh4_frontend_destroy; frontend->analyze_code = &sh4_frontend_analyze_code; frontend->translate_code = &sh4_frontend_translate_code; diff --git a/src/jit/frontend/sh4/sh4_frontend.h b/src/jit/frontend/sh4/sh4_frontend.h index 71a49167..75c814f4 100644 --- a/src/jit/frontend/sh4/sh4_frontend.h +++ b/src/jit/frontend/sh4/sh4_frontend.h @@ -1,7 +1,9 @@ #ifndef SH4_FRONTEND_H #define SH4_FRONTEND_H -#include "jit/frontend/jit_frontend.h" +#include "jit/jit_frontend.h" + +struct jit_guest; enum { SH4_DOUBLE_PR = 0x1, @@ -10,6 +12,6 @@ enum { extern uint32_t sh4_fsca_table[]; -struct jit_frontend *sh4_frontend_create(); +struct jit_frontend *sh4_frontend_create(struct jit_guest *guest); #endif diff --git a/src/jit/frontend/sh4/sh4_guest.h b/src/jit/frontend/sh4/sh4_guest.h index d334fa2a..42fb5210 100644 --- a/src/jit/frontend/sh4/sh4_guest.h +++ b/src/jit/frontend/sh4/sh4_guest.h @@ -2,7 +2,8 @@ #define SH4_GUEST_H #include -#include "jit/jit.h" +#include +#include "jit/jit_guest.h" /* * sh4 guest context @@ -181,12 +182,4 @@ struct sh4_guest { sh4_fpscr_updated_cb fpscr_updated; }; -static inline struct sh4_guest *sh4_guest_create() { - return calloc(1, sizeof(struct sh4_guest)); -} - -static inline void sh4_guest_destroy(struct sh4_guest *guest) { - free(guest); -} - #endif diff --git a/src/jit/jit.c b/src/jit/jit.c index 1d4d60a0..471a0b91 100644 --- a/src/jit/jit.c +++ b/src/jit/jit.c @@ -5,9 +5,9 @@ #include "core/filesystem.h" #include "core/option.h" #include "core/profiler.h" -#include "jit/backend/jit_backend.h" -#include "jit/frontend/jit_frontend.h" #include "jit/ir/ir.h" +#include "jit/jit_backend.h" +#include "jit/jit_frontend.h" #include "jit/passes/constant_propagation_pass.h" #include "jit/passes/dead_code_elimination_pass.h" #include "jit/passes/expression_simplification_pass.h" @@ -203,7 +203,7 @@ static struct jit_block *jit_alloc_block(struct jit *jit) { return block; } -void jit_free_blocks(struct jit *jit) { +void jit_free_code(struct jit *jit) { /* invalidate code pointers and remove block entries from lookup maps. this is only safe to use when no code is currently executing */ struct rb_node *it = rb_first(&jit->blocks); @@ -221,7 +221,7 @@ void jit_free_blocks(struct jit *jit) { jit->backend->reset(jit->backend); } -void jit_invalidate_blocks(struct jit *jit) { +void jit_invalidate_code(struct jit *jit) { /* invalidate code pointers, but don't remove block entries from lookup maps. this is used when clearing the jit while code is currently executing */ struct rb_node *it = rb_first(&jit->blocks); @@ -238,7 +238,7 @@ void jit_invalidate_blocks(struct jit *jit) { /* don't reset backend code buffers, code is still running */ } -void jit_add_edge(struct jit *jit, void *branch, uint32_t addr) { +void jit_link_code(struct jit *jit, void *branch, uint32_t addr) { struct jit_block *src = jit_lookup_block_reverse(jit, branch); struct jit_block *dst = jit_get_block(jit, addr); @@ -274,7 +274,7 @@ static void jit_dump_block(struct jit *jit, uint32_t guest_addr, fclose(file); } -void jit_compile_block(struct jit *jit, uint32_t guest_addr) { +void jit_compile_code(struct jit *jit, uint32_t guest_addr) { PROF_ENTER("cpu", "jit_compile_block"); #if 0 @@ -332,7 +332,7 @@ void jit_compile_block(struct jit *jit, uint32_t guest_addr) { #endif /* dump unoptimized block */ - if (jit->dump_blocks) { + if (jit->dump_code) { jit_dump_block(jit, guest_addr, &ir); } @@ -364,7 +364,7 @@ void jit_compile_block(struct jit *jit, uint32_t guest_addr) { /* if the backend overflowed, completely free the cache and let dispatch try to compile again */ LOG_INFO("backend overflow, resetting code cache"); - jit_free_blocks(jit); + jit_free_code(jit); } PROF_LEAVE(); @@ -420,7 +420,7 @@ void jit_destroy(struct jit *jit) { } if (jit->backend) { - jit_free_blocks(jit); + jit_free_code(jit); } if (jit->dce) { @@ -447,23 +447,14 @@ void jit_destroy(struct jit *jit) { } struct jit *jit_create(const char *tag, struct jit_frontend *frontend, - struct jit_backend *backend, struct jit_guest *guest) { + struct jit_backend *backend) { 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); + /* create optimization passes */ jit->lse = lse_create(); jit->cprop = cprop_create(); jit->esimp = esimp_create(); @@ -471,6 +462,10 @@ struct jit *jit_create(const char *tag, struct jit_frontend *frontend, jit->ra = ra_create(jit->backend->registers, jit->backend->num_registers, jit->backend->emitters, jit->backend->num_emitters); + /* setup exception handler to deal with self-modifying code and fastmem + related exceptions */ + jit->exc_handler = exception_handler_add(jit, &jit_handle_exception); + /* open perf map if enabled */ if (OPTION_perf) { #if PLATFORM_DARWIN || PLATFORM_LINUX @@ -482,8 +477,5 @@ struct jit *jit_create(const char *tag, struct jit_frontend *frontend, #endif } - jit->frontend->init(jit->frontend); - jit->backend->init(jit->backend); - return jit; } diff --git a/src/jit/jit.h b/src/jit/jit.h index 87ef1057..ad989fe0 100644 --- a/src/jit/jit.h +++ b/src/jit/jit.h @@ -14,10 +14,6 @@ struct lse; struct ra; struct val; -typedef void (*jit_interrupt_cb)(void *); -typedef uint32_t (*mem_read_cb)(void *, uint32_t, uint32_t); -typedef void (*mem_write_cb)(void *, uint32_t, uint32_t, uint32_t); - enum { JIT_BRANCH_STATIC, JIT_BRANCH_STATIC_TRUE, @@ -90,41 +86,11 @@ struct jit_edge { struct list_node out_it; }; -struct jit_guest { - /* mask used to directly map each guest address to a block of code */ - uint32_t addr_mask; - - /* runtime interface used by the backend when compiling each block's - prologue / epilogue */ - void *data; - int offset_pc; - int offset_cycles; - int offset_instrs; - int offset_interrupts; - jit_interrupt_cb check_interrupts; - - /* memory interface */ - void *ctx; - void *mem; - struct address_space *space; - void (*lookup)(struct address_space *, uint32_t, void **, void **, - mem_read_cb *, mem_write_cb *, uint32_t *); - uint8_t (*r8)(struct address_space *, uint32_t); - uint16_t (*r16)(struct address_space *, uint32_t); - uint32_t (*r32)(struct address_space *, uint32_t); - uint64_t (*r64)(struct address_space *, uint32_t); - void (*w8)(struct address_space *, uint32_t, uint8_t); - void (*w16)(struct address_space *, uint32_t, uint16_t); - void (*w32)(struct address_space *, uint32_t, uint32_t); - void (*w64)(struct address_space *, uint32_t, uint64_t); -}; - struct jit { char tag[32]; struct jit_frontend *frontend; struct jit_backend *backend; - struct jit_guest *guest; struct exception_handler *exc_handler; /* passes */ @@ -146,19 +112,19 @@ struct jit { FILE *perf_map; /* dump ir to application directory as blocks compile */ - int dump_blocks; + int dump_code; }; struct jit *jit_create(const char *tag, struct jit_frontend *frontend, - struct jit_backend *backend, struct jit_guest *guest); + struct jit_backend *backend); void jit_destroy(struct jit *jit); void jit_run(struct jit *jit, int cycles); -void jit_compile_block(struct jit *jit, uint32_t guest_addr); -void jit_add_edge(struct jit *jit, void *code, uint32_t dst); +void jit_compile_code(struct jit *jit, uint32_t guest_addr); +void jit_link_code(struct jit *jit, void *code, uint32_t target); -void jit_invalidate_blocks(struct jit *jit); -void jit_free_blocks(struct jit *jit); +void jit_invalidate_code(struct jit *jit); +void jit_free_code(struct jit *jit); #endif diff --git a/src/jit/backend/jit_backend.h b/src/jit/jit_backend.h similarity index 97% rename from src/jit/backend/jit_backend.h rename to src/jit/jit_backend.h index 99801aa8..6e90fe0e 100644 --- a/src/jit/backend/jit_backend.h +++ b/src/jit/jit_backend.h @@ -5,8 +5,8 @@ #include "jit/ir/ir.h" struct exception_state; -struct jit; struct jit_block; +struct jit_guest; /* macro to help declare a code buffer for the backends to use @@ -70,7 +70,7 @@ struct jit_emitter { }; struct jit_backend { - struct jit *jit; + struct jit_guest *guest; const struct jit_register *registers; int num_registers; @@ -78,7 +78,6 @@ struct jit_backend { const struct jit_emitter *emitters; int num_emitters; - void (*init)(struct jit_backend *); void (*destroy)(struct jit_backend *); /* compile interface */ diff --git a/src/jit/frontend/jit_frontend.h b/src/jit/jit_frontend.h similarity index 91% rename from src/jit/frontend/jit_frontend.h rename to src/jit/jit_frontend.h index 5a5ac9f5..77c0bf0e 100644 --- a/src/jit/frontend/jit_frontend.h +++ b/src/jit/jit_frontend.h @@ -4,7 +4,6 @@ #include struct ir; -struct jit; struct jit_block; struct jit_guest; struct jit_frontend; @@ -22,9 +21,8 @@ struct jit_opdef { }; struct jit_frontend { - struct jit *jit; + struct jit_guest *guest; - void (*init)(struct jit_frontend *); void (*destroy)(struct jit_frontend *); void (*analyze_code)(struct jit_frontend *, struct jit_block *); diff --git a/src/jit/jit_guest.h b/src/jit/jit_guest.h new file mode 100644 index 00000000..817d87fb --- /dev/null +++ b/src/jit/jit_guest.h @@ -0,0 +1,45 @@ +#ifndef JIT_GUEST_H +#define JIT_GUEST_H + +#include + +typedef uint32_t (*mem_read_cb)(void *, uint32_t, uint32_t); +typedef void (*mem_write_cb)(void *, uint32_t, uint32_t, uint32_t); + +typedef void (*jit_compile_cb)(void *, uint32_t); +typedef void (*jit_link_cb)(void *, uint32_t); +typedef void (*jit_interrupt_cb)(void *); + +struct address_space; + +struct jit_guest { + /* mask used to directly map each guest address to a block of code */ + uint32_t addr_mask; + + /* memory interface used by both the frontend and backend */ + void *ctx; + void *mem; + struct address_space *space; + void (*lookup)(struct address_space *, uint32_t, void **, void **, + mem_read_cb *, mem_write_cb *, uint32_t *); + uint8_t (*r8)(struct address_space *, uint32_t); + uint16_t (*r16)(struct address_space *, uint32_t); + uint32_t (*r32)(struct address_space *, uint32_t); + uint64_t (*r64)(struct address_space *, uint32_t); + void (*w8)(struct address_space *, uint32_t, uint8_t); + void (*w16)(struct address_space *, uint32_t, uint16_t); + void (*w32)(struct address_space *, uint32_t, uint32_t); + void (*w64)(struct address_space *, uint32_t, uint64_t); + + /* runtime interface used by the backend and dispatch */ + void *data; + int offset_pc; + int offset_cycles; + int offset_instrs; + int offset_interrupts; + jit_compile_cb compile_code; + jit_link_cb link_code; + jit_interrupt_cb check_interrupts; +}; + +#endif diff --git a/src/jit/pass_stats.c b/src/jit/pass_stats.c index 95da02a5..8381c3ad 100644 --- a/src/jit/pass_stats.c +++ b/src/jit/pass_stats.c @@ -15,7 +15,7 @@ void pass_stats_unregister(struct pass_stat *stat) { void pass_stats_dump() { LOG_INFO("===-----------------------------------------------------==="); - LOG_INFO("Pass stats"); + LOG_INFO("pass stats"); LOG_INFO("===-----------------------------------------------------==="); int w = 0; diff --git a/src/jit/passes/register_allocation_pass.c b/src/jit/passes/register_allocation_pass.c index 28028fb3..f249149a 100644 --- a/src/jit/passes/register_allocation_pass.c +++ b/src/jit/passes/register_allocation_pass.c @@ -2,8 +2,8 @@ #include "jit/passes/register_allocation_pass.h" #include "core/list.h" #include "core/math.h" -#include "jit/backend/jit_backend.h" #include "jit/ir/ir.h" +#include "jit/jit_backend.h" #include "jit/pass_stats.h" /* second-chance binpacking register allocator based off of the paper "Quality diff --git a/tools/recc/main.c b/tools/recc/main.c index 97c72aec..1ca4b912 100644 --- a/tools/recc/main.c +++ b/tools/recc/main.c @@ -2,27 +2,24 @@ #include "core/log.h" #include "core/option.h" #include "jit/backend/x64/x64_backend.h" -#include "jit/frontend/sh4/sh4_disasm.h" #include "jit/ir/ir.h" #include "jit/jit.h" +#include "jit/jit_guest.h" #include "jit/pass_stats.h" #include "jit/passes/constant_propagation_pass.h" -#include "jit/passes/conversion_elimination_pass.h" #include "jit/passes/dead_code_elimination_pass.h" #include "jit/passes/expression_simplification_pass.h" #include "jit/passes/load_store_elimination_pass.h" #include "jit/passes/register_allocation_pass.h" -DEFINE_OPTION_INT(help, 0, "Show help"); -DEFINE_OPTION_STRING(pass, "lse,cprop,cve,esimp,dce,ra", +DEFINE_OPTION_STRING(pass, "lse,cprop,esimp,dce,ra", "Comma-separated list of passes to run"); DEFINE_STAT(ir_instrs_total, "total ir instructions"); DEFINE_STAT(ir_instrs_removed, "removed ir instructions"); +DEFINE_JIT_CODE_BUFFER(code); static uint8_t ir_buffer[1024 * 1024]; -static uint8_t code[1024 * 1024]; -static int code_size = sizeof(code); static int get_num_instrs(const struct ir *ir) { int n = 0; @@ -54,7 +51,7 @@ static void sanitize_ir(struct ir *ir) { } } -static void process_file(struct jit *jit, const char *filename, +static void process_file(struct jit_backend *backend, const char *filename, int disable_dumps) { struct ir ir = {0}; ir.buffer = ir_buffer; @@ -71,7 +68,7 @@ static void process_file(struct jit *jit, const char *filename, sanitize_ir(&ir); /* run optimization passes */ - char passes[MAX_OPTION_LENGTH]; + char passes[OPTION_MAX_LENGTH]; strncpy(passes, OPTION_pass, sizeof(passes)); int num_instrs_before = get_num_instrs(&ir); @@ -95,18 +92,18 @@ 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(jit->backend->registers, jit->backend->num_registers); + struct ra *ra = ra_create(backend->registers, backend->num_registers, + backend->emitters, backend->num_emitters); ra_run(ra, &ir); ra_destroy(ra); } else { - LOG_WARNING("Unknown pass %s", name); + LOG_WARNING("unknown pass %s", name); } /* print ir after each pass if requested */ if (!disable_dumps) { LOG_INFO("===-----------------------------------------------------==="); - LOG_INFO("IR after %s", name); + LOG_INFO("ir after %s", name); LOG_INFO("===-----------------------------------------------------==="); ir_write(&ir, stdout); LOG_INFO(""); @@ -118,17 +115,16 @@ static void process_file(struct jit *jit, const char *filename, int num_instrs_after = get_num_instrs(&ir); /* assemble backend code */ - struct jit_block block; - - jit->backend->reset(jit->backend); - int res = jit->backend->assemble_code(jit->backend, &block, &ir); + struct jit_block block = {0}; + backend->reset(backend); + int res = backend->assemble_code(backend, &block, &ir); CHECK(res); if (!disable_dumps) { LOG_INFO("===-----------------------------------------------------==="); - LOG_INFO("X64 code"); + LOG_INFO("x64 code"); LOG_INFO("===-----------------------------------------------------==="); - jit->backend->dump_code(jit->backend, block.host_addr, block.host_size); + backend->dump_code(backend, &block); LOG_INFO(""); } @@ -137,11 +133,11 @@ static void process_file(struct jit *jit, const char *filename, STAT_ir_instrs_removed += num_instrs_before - num_instrs_after; } -static void process_dir(struct jit *jit, const char *path) { +static void process_dir(struct jit_backend *backend, const char *path) { DIR *dir = opendir(path); if (!dir) { - LOG_WARNING("Failed to open directory %s", path); + LOG_WARNING("failed to open directory %s", path); return; } @@ -156,48 +152,35 @@ static void process_dir(struct jit *jit, const char *path) { snprintf(filename, sizeof(filename), "%s" PATH_SEPARATOR "%s", path, ent->d_name); - LOG_INFO("Processing %s", filename); + LOG_INFO("processing %s", filename); - process_file(jit, filename, 1); + process_file(backend, filename, 1); } closedir(dir); } int main(int argc, char **argv) { - options_parse(&argc, &argv); - - if (OPTION_help) { - options_print_help(); - return EXIT_SUCCESS; + if (!options_parse(&argc, &argv)) { + return EXIT_FAILURE; } const char *path = argv[1]; struct jit_guest guest = {0}; - guest.r8 = (void *)code; - guest.r16 = (void *)code; - guest.r32 = (void *)code; - guest.w8 = (void *)code; - guest.w16 = (void *)code; - guest.w32 = (void *)code; + guest.addr_mask = 0xff; - struct jit_backend *backend = x64_backend_create(code, code_size); - - /* initailize jit, stubbing out guest interfaces that are used during - assembly to a valid address */ - struct jit *jit = jit_create("recc", NULL, backend, &guest); + struct jit_backend *backend = x64_backend_create(&guest, code, sizeof(code)); if (fs_isfile(path)) { - process_file(jit, path, 0); + process_file(backend, path, 0); } else { - process_dir(jit, path); + process_dir(backend, path); } LOG_INFO(""); pass_stats_dump(); - jit_destroy(jit); backend->destroy(backend); return EXIT_SUCCESS; diff --git a/tools/retrace/depth.c b/tools/retrace/depth.c index 662993e6..2e17313f 100644 --- a/tools/retrace/depth.c +++ b/tools/retrace/depth.c @@ -2,8 +2,8 @@ #include #include "core/assert.h" #include "core/sort.h" +#include "file/trace.h" #include "guest/pvr/tr.h" -#include "guest/pvr/trace.h" struct depth_entry { /* vertex index */