mirror of https://github.com/inolen/redream.git
added SH4_FLAG_LOAD_PC to synchronize pc before instructions which need to load it
This commit is contained in:
parent
54e61ef637
commit
c8b7b1b304
|
@ -114,7 +114,7 @@ static void sh4_invalid_instr(void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
LOG_FATAL("Unhandled invalid instruction at 0x%08x", sh4->ctx.pc);
|
||||
LOG_FATAL("unhandled invalid instruction at 0x%08x", sh4->ctx.pc);
|
||||
}
|
||||
|
||||
static void sh4_run(struct device *dev, int64_t ns) {
|
||||
|
|
|
@ -310,8 +310,8 @@ static void x64_backend_emit_epilogue(struct x64_backend *backend,
|
|||
struct jit_block *block) {
|
||||
auto &e = *backend->codegen;
|
||||
|
||||
/* catch blocks that haven't been terminated */
|
||||
e.db(0xcc);
|
||||
/* if the block didn't branch to another address, return to dispatch */
|
||||
e.jmp(backend->dispatch_dynamic);
|
||||
}
|
||||
|
||||
static void x64_backend_emit_prologue(struct x64_backend *backend,
|
||||
|
@ -353,23 +353,12 @@ static void x64_backend_emit(struct x64_backend *backend,
|
|||
|
||||
e.L(block_label);
|
||||
|
||||
int terminated = 0;
|
||||
|
||||
list_for_each_entry(instr, &blk->instrs, struct ir_instr, it) {
|
||||
struct jit_emitter *emitter = &x64_emitters[instr->op];
|
||||
x64_emit_cb emit = (x64_emit_cb)emitter->func;
|
||||
CHECK_NOTNULL(emit);
|
||||
|
||||
emit(backend, *backend->codegen, block, instr);
|
||||
|
||||
terminated = (instr->op == OP_BRANCH);
|
||||
}
|
||||
|
||||
/* if the block doesn't terminate in an unconditional branch, dispatch to
|
||||
the next pc, which has ideally been set by a non-branch operation such
|
||||
as a fallback handler */
|
||||
if (!terminated) {
|
||||
e.jmp(backend->dispatch_dynamic);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,10 @@ enum {
|
|||
SH4_FLAG_COND = 0x8,
|
||||
SH4_FLAG_CMP = 0x10,
|
||||
SH4_FLAG_DELAYED = 0x20,
|
||||
SH4_FLAG_SET_PC = 0x40,
|
||||
SH4_FLAG_SET_FPSCR = 0x80,
|
||||
SH4_FLAG_SET_SR = 0x100,
|
||||
SH4_FLAG_LOAD_PC = 0x40,
|
||||
SH4_FLAG_STORE_PC = 0x80,
|
||||
SH4_FLAG_STORE_FPSCR = 0x100,
|
||||
SH4_FLAG_STORE_SR = 0x200,
|
||||
};
|
||||
|
||||
enum sh4_op {
|
||||
|
|
|
@ -32,7 +32,9 @@ static void sh4_frontend_dump_code(struct jit_frontend *base,
|
|||
|
||||
char buffer[128];
|
||||
|
||||
for (int offset = 0; offset < block->guest_size; offset += 2) {
|
||||
int offset = 0;
|
||||
|
||||
while (offset < block->guest_size) {
|
||||
uint32_t addr = block->guest_addr + offset;
|
||||
uint16_t data = guest->r16(guest->space, addr);
|
||||
union sh4_instr instr = {data};
|
||||
|
@ -41,8 +43,10 @@ static void sh4_frontend_dump_code(struct jit_frontend *base,
|
|||
sh4_format(addr, instr, buffer, sizeof(buffer));
|
||||
LOG_INFO(buffer);
|
||||
|
||||
offset += 2;
|
||||
|
||||
if (def->flags & SH4_FLAG_DELAYED) {
|
||||
uint32_t delay_addr = addr + 2;
|
||||
uint32_t delay_addr = block->guest_addr + offset;
|
||||
uint16_t delay_data = guest->r16(guest->space, delay_addr);
|
||||
union sh4_instr delay_instr = {delay_data};
|
||||
|
||||
|
@ -72,30 +76,54 @@ static void sh4_frontend_translate_code(struct jit_frontend *base,
|
|||
}
|
||||
|
||||
/* translate the actual block */
|
||||
int end_flags = 0;
|
||||
int offset = 0;
|
||||
struct jit_opdef *def = NULL;
|
||||
struct ir_insert_point delay_point;
|
||||
|
||||
for (int offset = 0; offset < block->guest_size; offset += 2) {
|
||||
while (offset < block->guest_size) {
|
||||
uint32_t addr = block->guest_addr + offset;
|
||||
uint16_t data = guest->r16(guest->space, addr);
|
||||
union sh4_instr instr = {data};
|
||||
struct jit_opdef *def = sh4_get_opdef(data);
|
||||
|
||||
#if 0
|
||||
/* emit a call to the interpreter fallback for each instruction. this can
|
||||
be used to bisect and find bad ir op implementations */
|
||||
ir_fallback(ir, def->fallback, addr, data);
|
||||
end_flags = SH4_FLAG_SET_PC;
|
||||
#else
|
||||
sh4_translate_cb cb = sh4_get_translator(data);
|
||||
CHECK_NOTNULL(cb);
|
||||
def = sh4_get_opdef(data);
|
||||
|
||||
/* emit synthetic op responsible for mapping guest to host instructions */
|
||||
ir_source_info(ir, addr, offset / 2);
|
||||
cb(guest, block, ir, addr, instr, flags);
|
||||
|
||||
end_flags = def->flags;
|
||||
#endif
|
||||
/* the pc is normally only written to the context at the end of the block,
|
||||
sync now for any instruction which needs to read the correct pc */
|
||||
if (def->flags & SH4_FLAG_LOAD_PC) {
|
||||
ir_store_context(ir, offsetof(struct sh4_context, pc),
|
||||
ir_alloc_i32(ir, addr));
|
||||
}
|
||||
|
||||
cb(guest, block, ir, addr, instr, flags, &delay_point);
|
||||
|
||||
offset += 2;
|
||||
|
||||
if (def->flags & SH4_FLAG_DELAYED) {
|
||||
uint32_t delay_addr = block->guest_addr + offset;
|
||||
uint32_t delay_data = guest->r16(guest->space, delay_addr);
|
||||
union sh4_instr delay_instr = {delay_data};
|
||||
sh4_translate_cb delay_cb = sh4_get_translator(delay_data);
|
||||
struct jit_opdef *delay_def = sh4_get_opdef(delay_data);
|
||||
|
||||
/* move insert point back to the middle of the last instruction */
|
||||
struct ir_insert_point original = ir_get_insert_point(ir);
|
||||
ir_set_insert_point(ir, &delay_point);
|
||||
|
||||
ir_source_info(ir, delay_addr, offset / 2);
|
||||
|
||||
if (delay_def->flags & SH4_FLAG_LOAD_PC) {
|
||||
ir_store_context(ir, offsetof(struct sh4_context, pc),
|
||||
ir_alloc_i32(ir, delay_addr));
|
||||
}
|
||||
|
||||
delay_cb(guest, block, ir, delay_addr, delay_instr, flags, NULL);
|
||||
|
||||
/* restore insert point */
|
||||
ir_set_insert_point(ir, &original);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
|
@ -110,11 +138,11 @@ static void sh4_frontend_translate_code(struct jit_frontend *base,
|
|||
|
||||
c.) the block terminates due to an instruction which sets the pc but is not
|
||||
a branch (e.g. an invalid instruction trap); nothing needs to be done,
|
||||
the backend will always implicitly branch to the next pc */
|
||||
dispatch will always implicitly branch to the next pc */
|
||||
|
||||
/* if the final instruction doesn't unconditionally set the pc, insert a
|
||||
branch to the next instruction */
|
||||
if ((end_flags & (SH4_FLAG_SET_PC | SH4_FLAG_COND)) != SH4_FLAG_SET_PC) {
|
||||
if ((def->flags & (SH4_FLAG_STORE_PC | SH4_FLAG_COND)) != SH4_FLAG_STORE_PC) {
|
||||
struct ir_block *tail_block =
|
||||
list_last_entry(&ir->blocks, struct ir_block, it);
|
||||
struct ir_instr *tail_instr =
|
||||
|
@ -156,7 +184,8 @@ static void sh4_frontend_analyze_code(struct jit_frontend *base,
|
|||
all_flags |= def->flags;
|
||||
|
||||
if (def->flags & SH4_FLAG_DELAYED) {
|
||||
uint32_t delay_data = guest->r16(guest->space, addr + 2);
|
||||
uint32_t delay_addr = block->guest_addr + offset;
|
||||
uint32_t delay_data = guest->r16(guest->space, delay_addr);
|
||||
struct jit_opdef *delay_def = sh4_get_opdef(delay_data);
|
||||
|
||||
offset += 2;
|
||||
|
@ -164,7 +193,6 @@ static void sh4_frontend_analyze_code(struct jit_frontend *base,
|
|||
block->num_cycles += delay_def->cycles;
|
||||
block->num_instrs++;
|
||||
|
||||
/* if the instruction has none of the IDLE_MASK flags, disqualify */
|
||||
idle_loop &= (delay_def->flags & IDLE_MASK) != 0;
|
||||
all_flags |= delay_def->flags;
|
||||
|
||||
|
@ -173,7 +201,7 @@ static void sh4_frontend_analyze_code(struct jit_frontend *base,
|
|||
}
|
||||
|
||||
/* stop emitting once a branch is hit and save off branch information */
|
||||
if (def->flags & SH4_FLAG_SET_PC) {
|
||||
if (def->flags & SH4_FLAG_STORE_PC) {
|
||||
if (def->op == SH4_OP_INVALID) {
|
||||
block->branch_type = JIT_BRANCH_DYNAMIC;
|
||||
} else if (def->op == SH4_OP_BF) {
|
||||
|
@ -235,13 +263,13 @@ static void sh4_frontend_analyze_code(struct jit_frontend *base,
|
|||
/* if fpscr has changed, stop emitting since the fpu state is invalidated.
|
||||
also, if sr has changed, stop emitting as there are interrupts that
|
||||
possibly need to be handled */
|
||||
if (def->flags & (SH4_FLAG_SET_FPSCR | SH4_FLAG_SET_SR)) {
|
||||
if (def->flags & (SH4_FLAG_STORE_FPSCR | SH4_FLAG_STORE_SR)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if there was no load, disqualify */
|
||||
idle_loop &= (all_flags & SH4_FLAG_LOAD) != 0;
|
||||
/* if the block doesn't contain the required flags, disqualify */
|
||||
idle_loop &= (all_flags & IDLE_MASK) == IDLE_MASK;
|
||||
|
||||
/* if the branch isn't a short back edge, disqualify */
|
||||
idle_loop &= (block->guest_addr - block->branch_addr) <= 32;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* NAME DESC INSTR_CODE CYCLES FLAGS
|
||||
*/
|
||||
|
||||
SH4_INSTR(INVALID, "invalid", 0000000000000000, 1, SH4_FLAG_SET_PC)
|
||||
SH4_INSTR(INVALID, "invalid", 0000000000000000, 1, SH4_FLAG_LOAD_PC | SH4_FLAG_STORE_PC)
|
||||
|
||||
/* fixed-point transfer instructions */
|
||||
SH4_INSTR(MOVI, "mov #imm8, rn", 1110nnnniiiiiiii, 1, 0)
|
||||
|
@ -119,31 +119,31 @@ SH4_INSTR(SHLR16, "shlr16 rn", 0100nnnn00101001, 1, 0)
|
|||
|
||||
|
||||
/* branch instructions */
|
||||
SH4_INSTR(BF, "bf disp:8", 10001011dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_SET_PC)
|
||||
SH4_INSTR(BFS, "bfs disp:8", 10001111dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BT, "bt disp:8", 10001001dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_SET_PC)
|
||||
SH4_INSTR(BTS, "bts disp:8", 10001101dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BRA, "bra disp:12", 1010dddddddddddd, 1, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BRAF, "braf rn", 0000nnnn00100011, 2, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BSR, "bsr disp:12", 1011dddddddddddd, 1, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BSRF, "bsrf rn", 0000nnnn00000011, 2, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(JMP, "jmp @rm", 0100nnnn00101011, 2, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(JSR, "jsr @rn", 0100nnnn00001011, 2, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(RTS, "rts", 0000000000001011, 2, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BF, "bf disp:8", 10001011dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_STORE_PC)
|
||||
SH4_INSTR(BFS, "bfs disp:8", 10001111dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BT, "bt disp:8", 10001001dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_STORE_PC)
|
||||
SH4_INSTR(BTS, "bts disp:8", 10001101dddddddd, 1, SH4_FLAG_COND | SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BRA, "bra disp:12", 1010dddddddddddd, 1, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BRAF, "braf rn", 0000nnnn00100011, 2, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BSR, "bsr disp:12", 1011dddddddddddd, 1, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(BSRF, "bsrf rn", 0000nnnn00000011, 2, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(JMP, "jmp @rm", 0100nnnn00101011, 2, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(JSR, "jsr @rn", 0100nnnn00001011, 2, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
SH4_INSTR(RTS, "rts", 0000000000001011, 2, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED)
|
||||
|
||||
|
||||
/* system control instructions */
|
||||
SH4_INSTR(CLRMAC, "clrmac", 0000000000101000, 1, 0)
|
||||
SH4_INSTR(CLRS, "clrs", 0000000001001000, 1, 0)
|
||||
SH4_INSTR(CLRT, "clrt", 0000000000001000, 1, 0)
|
||||
SH4_INSTR(LDCSR, "ldc rn, sr", 0100mmmm00001110, 4, SH4_FLAG_SET_SR)
|
||||
SH4_INSTR(LDCSR, "ldc rn, sr", 0100mmmm00001110, 4, SH4_FLAG_STORE_SR)
|
||||
SH4_INSTR(LDCGBR, "ldc rn, gbr", 0100mmmm00011110, 3, 0)
|
||||
SH4_INSTR(LDCVBR, "ldc rn, vbr", 0100mmmm00101110, 1, 0)
|
||||
SH4_INSTR(LDCSSR, "ldc rn, ssr", 0100mmmm00111110, 1, 0)
|
||||
SH4_INSTR(LDCSPC, "ldc rn, spc", 0100mmmm01001110, 1, 0)
|
||||
SH4_INSTR(LDCDBR, "ldc rn, dbr", 0100mmmm11111010, 1, 0)
|
||||
SH4_INSTR(LDCRBANK, "ldc.l rn, rn_bank", 0100mmmm1nnn1110, 1, 0)
|
||||
SH4_INSTR(LDCMSR, "ldc.l @rn+, sr", 0100mmmm00000111, 4, SH4_FLAG_LOAD | SH4_FLAG_SET_SR)
|
||||
SH4_INSTR(LDCMSR, "ldc.l @rn+, sr", 0100mmmm00000111, 4, SH4_FLAG_LOAD | SH4_FLAG_STORE_SR)
|
||||
SH4_INSTR(LDCMGBR, "ldc.l @rn+, gbr", 0100mmmm00010111, 3, SH4_FLAG_LOAD)
|
||||
SH4_INSTR(LDCMVBR, "ldc.l @rn+, vbr", 0100mmmm00100111, 1, SH4_FLAG_LOAD)
|
||||
SH4_INSTR(LDCMSSR, "ldc.l @rn+, ssr", 0100mmmm00110111, 1, SH4_FLAG_LOAD)
|
||||
|
@ -163,10 +163,10 @@ SH4_INSTR(OCBI, "ocbi", 0000nnnn10010011, 1, 0)
|
|||
SH4_INSTR(OCBP, "ocbp", 0000nnnn10100011, 1, 0)
|
||||
SH4_INSTR(OCBWB, "ocbwb", 0000nnnn10110011, 1, 0)
|
||||
SH4_INSTR(PREF, "pref @rn", 0000nnnn10000011, 1, SH4_FLAG_STORE)
|
||||
SH4_INSTR(RTE, "rte", 0000000000101011, 5, SH4_FLAG_SET_PC | SH4_FLAG_DELAYED | SH4_FLAG_SET_SR)
|
||||
SH4_INSTR(RTE, "rte", 0000000000101011, 5, SH4_FLAG_STORE_PC | SH4_FLAG_DELAYED | SH4_FLAG_STORE_SR)
|
||||
SH4_INSTR(SETS, "sets", 0000000001011000, 1, 0)
|
||||
SH4_INSTR(SETT, "sett", 0000000000011000, 1, 0)
|
||||
SH4_INSTR(SLEEP, "sleep", 0000000000011011, 4, SH4_FLAG_SET_PC)
|
||||
SH4_INSTR(SLEEP, "sleep", 0000000000011011, 4, SH4_FLAG_STORE_PC)
|
||||
SH4_INSTR(STCSR, "stc sr, rn", 0000nnnn00000010, 2, 0)
|
||||
SH4_INSTR(STCGBR, "stc gbr, rn", 0000nnnn00010010, 2, 0)
|
||||
SH4_INSTR(STCVBR, "stc vbr, rn", 0000nnnn00100010, 2, 0)
|
||||
|
@ -189,7 +189,7 @@ SH4_INSTR(STSPR, "sts pr, rn", 0000nnnn00101010, 2, 0)
|
|||
SH4_INSTR(STSMMACH, "sts.l mach, @-rn", 0100nnnn00000010, 1, SH4_FLAG_STORE)
|
||||
SH4_INSTR(STSMMACL, "sts.l macl, @-rn", 0100nnnn00010010, 1, SH4_FLAG_STORE)
|
||||
SH4_INSTR(STSMPR, "sts.l pr, @-rn", 0100nnnn00100010, 2, SH4_FLAG_STORE)
|
||||
SH4_INSTR(TRAPA, "trapa #imm8", 11000011iiiiiiii, 7, SH4_FLAG_SET_PC)
|
||||
SH4_INSTR(TRAPA, "trapa #imm8", 11000011iiiiiiii, 7, SH4_FLAG_STORE_PC)
|
||||
|
||||
|
||||
/* floating-point single and double precision instructions */
|
||||
|
@ -226,9 +226,9 @@ SH4_INSTR(FCNVSD, "fcnvsd fpul, drn", 1111nnnn10101101, 1, 0)
|
|||
|
||||
|
||||
/* floating-point control instructions */
|
||||
SH4_INSTR(LDSFPSCR, "lds rn, fpscr", 0100mmmm01101010, 1, SH4_FLAG_SET_FPSCR)
|
||||
SH4_INSTR(LDSFPSCR, "lds rn, fpscr", 0100mmmm01101010, 1, SH4_FLAG_STORE_FPSCR)
|
||||
SH4_INSTR(LDSFPUL, "lds rn, fpul", 0100mmmm01011010, 1, 0)
|
||||
SH4_INSTR(LDSMFPSCR, "lds.l @rn+, fpscr", 0100mmmm01100110, 1, SH4_FLAG_LOAD | SH4_FLAG_SET_FPSCR)
|
||||
SH4_INSTR(LDSMFPSCR, "lds.l @rn+, fpscr", 0100mmmm01100110, 1, SH4_FLAG_LOAD | SH4_FLAG_STORE_FPSCR)
|
||||
SH4_INSTR(LDSMFPUL, "lds.l @rn+, fpul", 0100mmmm01010110, 1, SH4_FLAG_LOAD)
|
||||
SH4_INSTR(STSFPSCR, "sts fpscr, rn", 0000nnnn01101010, 1, 0)
|
||||
SH4_INSTR(STSFPUL, "sts fpul, rn", 0000nnnn01011010, 1, 0)
|
||||
|
@ -241,5 +241,5 @@ SH4_INSTR(STSMFPUL, "sts.l fpul, @-rn", 0100nnnn01010010, 1, SH4_FL
|
|||
SH4_INSTR(FIPR, "fipr fvm, fvn", 1111nnmm11101101, 1, 0)
|
||||
SH4_INSTR(FSCA, "fsca fpul, drn", 1111nnn011111101, 1, 0)
|
||||
SH4_INSTR(FTRV, "ftrv xmtrx, fvn", 1111nn0111111101, 1, 0)
|
||||
SH4_INSTR(FRCHG, "frchg", 1111101111111101, 1, SH4_FLAG_SET_FPSCR)
|
||||
SH4_INSTR(FSCHG, "fschg", 1111001111111101, 1, SH4_FLAG_SET_FPSCR)
|
||||
SH4_INSTR(FRCHG, "frchg", 1111101111111101, 1, SH4_FLAG_STORE_FPSCR)
|
||||
SH4_INSTR(FSCHG, "fschg", 1111001111111101, 1, SH4_FLAG_STORE_FPSCR)
|
||||
|
|
|
@ -96,16 +96,7 @@ static void store_fpscr(struct sh4_guest *guest, struct ir *ir,
|
|||
#define FPU_DOUBLE_PR (flags & SH4_DOUBLE_PR)
|
||||
#define FPU_DOUBLE_SZ (flags & SH4_DOUBLE_SZ)
|
||||
|
||||
#define DELAY_INSTR() { \
|
||||
uint32_t delay_addr = addr + 2; \
|
||||
uint32_t delay_offset = delay_addr - block->guest_addr; \
|
||||
uint16_t delay_data = guest->r16(guest->space, delay_addr); \
|
||||
union sh4_instr delay_instr = {delay_data}; \
|
||||
sh4_translate_cb cb = sh4_get_translator(delay_data); \
|
||||
CHECK_NOTNULL(cb); \
|
||||
ir_source_info(ir, delay_addr, delay_offset / 2); \
|
||||
cb(guest, block, ir, delay_addr, delay_instr, flags); \
|
||||
}
|
||||
#define DELAY_INSTR() *delay_point = ir_get_insert_point(ir);
|
||||
#define NEXT_INSTR()
|
||||
#define NEXT_NEXT_INSTR()
|
||||
|
||||
|
@ -459,7 +450,7 @@ static void store_fpscr(struct sh4_guest *guest, struct ir *ir,
|
|||
#define INSTR(name) \
|
||||
void sh4_translate_##name(struct sh4_guest *guest, struct jit_block *block, \
|
||||
struct ir *ir, uint32_t addr, union sh4_instr i, \
|
||||
int flags)
|
||||
int flags, struct ir_insert_point *delay_point)
|
||||
#include "jit/frontend/sh4/sh4_instr.h"
|
||||
#undef INSTR
|
||||
|
||||
|
@ -468,3 +459,9 @@ sh4_translate_cb sh4_translators[NUM_SH4_OPS] = {
|
|||
#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;
|
||||
}
|
||||
|
|
|
@ -4,16 +4,14 @@
|
|||
#include "jit/frontend/sh4/sh4_disasm.h"
|
||||
|
||||
struct ir;
|
||||
struct ir_insert_point;
|
||||
struct jit_block;
|
||||
struct sh4_guest;
|
||||
|
||||
typedef void (*sh4_translate_cb)(struct sh4_guest *, struct jit_block *,
|
||||
struct ir *, uint32_t, union sh4_instr, int);
|
||||
struct ir *, uint32_t, union sh4_instr, int,
|
||||
struct ir_insert_point *);
|
||||
|
||||
extern sh4_translate_cb sh4_translators[NUM_SH4_OPS];
|
||||
|
||||
static inline sh4_translate_cb sh4_get_translator(uint16_t instr) {
|
||||
return sh4_translators[sh4_get_op(instr)];
|
||||
}
|
||||
sh4_translate_cb sh4_get_translator(uint16_t instr);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue