mirror of https://github.com/inolen/redream.git
added SH4_FLAG_FALLBACK to explicitly flag instructions to fallback to the interpreter
This commit is contained in:
parent
e7ea5fcd70
commit
0263b127d6
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue