added SH4_FLAG_FALLBACK to explicitly flag instructions to fallback to the interpreter

This commit is contained in:
Anthony Pesch 2017-11-18 14:10:32 -05:00
parent e7ea5fcd70
commit 0263b127d6
4 changed files with 57 additions and 42 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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:

View File

@ -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)];
}