From 0263b127d6fed94ff1d4a39288f93ac6e0b14094 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Sat, 18 Nov 2017 14:10:32 -0500 Subject: [PATCH] added SH4_FLAG_FALLBACK to explicitly flag instructions to fallback to the interpreter --- src/jit/frontend/sh4/sh4_disasm.c | 5 -- src/jit/frontend/sh4/sh4_disasm.h | 2 +- src/jit/frontend/sh4/sh4_frontend.c | 83 +++++++++++++++++----------- src/jit/frontend/sh4/sh4_translate.c | 9 +-- 4 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/jit/frontend/sh4/sh4_disasm.c b/src/jit/frontend/sh4/sh4_disasm.c index 40044ec8..f03b3272 100644 --- a/src/jit/frontend/sh4/sh4_disasm.c +++ b/src/jit/frontend/sh4/sh4_disasm.c @@ -60,11 +60,6 @@ void sh4_format(uint32_t addr, union sh4_instr i, char *buffer, size_t buffer_size) { struct jit_opdef *def = sh4_get_opdef(i.raw); - if (def->flags & SH4_FLAG_INVALID) { - snprintf(buffer, buffer_size, "0x%08x .word 0x%04x", addr, i.raw); - return; - } - char value[128]; size_t value_len; uint32_t movsize; diff --git a/src/jit/frontend/sh4/sh4_disasm.h b/src/jit/frontend/sh4/sh4_disasm.h index 6ab5e3fa..f2a13bf8 100644 --- a/src/jit/frontend/sh4/sh4_disasm.h +++ b/src/jit/frontend/sh4/sh4_disasm.h @@ -5,7 +5,7 @@ #include "jit/jit_frontend.h" enum { - SH4_FLAG_INVALID = 0x1, + SH4_FLAG_FALLBACK = 0x1, SH4_FLAG_LOAD = 0x2, SH4_FLAG_STORE = 0x4, SH4_FLAG_COND = 0x8, diff --git a/src/jit/frontend/sh4/sh4_frontend.c b/src/jit/frontend/sh4/sh4_frontend.c index c86ad67f..20404963 100644 --- a/src/jit/frontend/sh4/sh4_frontend.c +++ b/src/jit/frontend/sh4/sh4_frontend.c @@ -182,42 +182,61 @@ static void sh4_frontend_translate_code(struct jit_frontend *base, ir_alloc_i32(ir, addr)); } - /* emit the instruction's translation. note, if the instruction has a delay - slot, delay_point is assigned where the slot's translation should be - emitted */ - struct ir_insert_point delay_point; + /* emit the instruction's translation if available */ sh4_translate_cb cb = sh4_get_translator(data); - cb(guest, ir, addr, instr, flags, &delay_point); - offset += 2; - - /* emit the delay slot's translation */ - if (def->flags & SH4_FLAG_DELAYED) { - uint32_t delay_addr = begin_addr + offset; - uint32_t delay_data = guest->r16(guest->mem, delay_addr); - union sh4_instr delay_instr = {delay_data}; - struct jit_opdef *delay_def = sh4_get_opdef(delay_data); - - use_fpscr |= - (delay_def->flags & SH4_FLAG_USE_FPSCR) == SH4_FLAG_USE_FPSCR; - - /* move insert point back to the middle of the preceding instruction */ - struct ir_insert_point original = ir_get_insert_point(ir); - ir_set_insert_point(ir, &delay_point); - - if (delay_def->flags & SH4_FLAG_LOAD_PC) { - ir_store_context(ir, offsetof(struct sh4_context, pc), - ir_alloc_i32(ir, delay_addr)); - } - - sh4_translate_cb delay_cb = sh4_get_translator(delay_data); - delay_cb(guest, ir, delay_addr, delay_instr, flags, NULL); - - /* restore insert point */ - ir_set_insert_point(ir, &original); + if (cb) { + /* if the instruction has a delay slot, delay_point is assigned where the + slot's translation should be emitted */ + struct ir_insert_point delay_point; + cb(guest, ir, addr, instr, flags, &delay_point); offset += 2; - was_delay = 1; + + if (def->flags & SH4_FLAG_DELAYED) { + uint32_t delay_addr = begin_addr + offset; + uint32_t delay_data = guest->r16(guest->mem, delay_addr); + union sh4_instr delay_instr = {delay_data}; + struct jit_opdef *delay_def = sh4_get_opdef(delay_data); + + use_fpscr |= + (delay_def->flags & SH4_FLAG_USE_FPSCR) == SH4_FLAG_USE_FPSCR; + + /* move insert point back to the middle of the preceding instruction */ + struct ir_insert_point original = ir_get_insert_point(ir); + ir_set_insert_point(ir, &delay_point); + + if (delay_def->flags & SH4_FLAG_LOAD_PC) { + ir_store_context(ir, offsetof(struct sh4_context, pc), + ir_alloc_i32(ir, delay_addr)); + } + + /* emit the delay slot's translation if available */ + sh4_translate_cb delay_cb = sh4_get_translator(delay_data); + + if (delay_cb) { + delay_cb(guest, ir, delay_addr, delay_instr, flags, NULL); + } else { + ir_fallback(ir, delay_def->fallback, delay_addr, delay_data); + } + + /* restore insert point */ + ir_set_insert_point(ir, &original); + + offset += 2; + was_delay = 1; + } + } else { + ir_fallback(ir, def->fallback, addr, data); + + offset += 2; + + /* don't emit a fallback for the delay slot, the original fallback will + execute it */ + if (def->flags & SH4_FLAG_DELAYED) { + offset += 2; + was_delay = 1; + } } /* there are 3 possible block endings: diff --git a/src/jit/frontend/sh4/sh4_translate.c b/src/jit/frontend/sh4/sh4_translate.c index 8686d382..7e65d057 100644 --- a/src/jit/frontend/sh4/sh4_translate.c +++ b/src/jit/frontend/sh4/sh4_translate.c @@ -454,13 +454,14 @@ static void store_fpscr(struct sh4_guest *guest, struct ir *ir, #undef INSTR sh4_translate_cb sh4_translators[NUM_SH4_OPS] = { -#define SH4_INSTR(name, desc, sig, cycles, flags) &sh4_translate_##name, +/* don't fill in an entry for the instruction if it's explicitly flagged to + fallback to the interpreter */ +#define SH4_INSTR(name, desc, sig, cycles, flags) \ + !((flags)&SH4_FLAG_FALLBACK) ? &sh4_translate_##name : NULL, #include "jit/frontend/sh4/sh4_instr.inc" #undef SH4_INSTR }; sh4_translate_cb sh4_get_translator(uint16_t instr) { - sh4_translate_cb cb = sh4_translators[sh4_get_op(instr)]; - CHECK_NOTNULL(cb); - return cb; + return sh4_translators[sh4_get_op(instr)]; }