diff options
Diffstat (limited to 'm68k_to_x86.c')
-rw-r--r-- | m68k_to_x86.c | 67 |
1 files changed, 60 insertions, 7 deletions
diff --git a/m68k_to_x86.c b/m68k_to_x86.c index 3896ba6..8b57091 100644 --- a/m68k_to_x86.c +++ b/m68k_to_x86.c @@ -23,7 +23,8 @@ char disasm_buf[1024]; -void handle_cycle_limit_int(); +m68k_context * sync_components(m68k_context * context, uint32_t address); + void handle_cycle_limit(); void m68k_save_context(); void m68k_load_context(); @@ -48,13 +49,13 @@ uint8_t * cycles(uint8_t * dst, uint32_t num) return dst; } -uint8_t * check_cycles_int(uint8_t * dst, uint32_t address) +uint8_t * check_cycles_int(uint8_t * dst, uint32_t address, x86_68k_options * opts) { dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); uint8_t * jmp_off = dst+1; dst = jcc(dst, CC_NC, dst + 7); dst = mov_ir(dst, address, SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)handle_cycle_limit_int); + dst = call(dst, opts->handle_cycle_limit_int); *jmp_off = dst - (jmp_off+1); return dst; } @@ -2746,7 +2747,7 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) { uint8_t * end_off, *zero_off, *norm_off; uint8_t dst_reg; - dst = check_cycles_int(dst, inst->address); + dst = check_cycles_int(dst, inst->address, opts); if (inst->op == M68K_MOVE) { return translate_m68k_move(dst, inst, opts); } else if(inst->op == M68K_LEA) { @@ -4089,7 +4090,7 @@ void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_ha native = call(native, bp_stub); //Calculate length of prologue - dst = check_cycles_int(dst, address); + dst = check_cycles_int(dst, address, opts); int check_int_size = dst-bp_stub; dst = bp_stub; @@ -4107,7 +4108,7 @@ void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_ha dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); uint8_t * jmp_off = dst+1; dst = jcc(dst, CC_NC, dst + 7); - dst = call(dst, (uint8_t *)handle_cycle_limit_int); + dst = call(dst, opts->handle_cycle_limit_int); *jmp_off = dst - (jmp_off+1); //jump back to body of translated instruction dst = pop_r(dst, SCRATCH1); @@ -4122,7 +4123,7 @@ void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_ha void remove_breakpoint(m68k_context * context, uint32_t address) { uint8_t * native = get_native_address(context->native_code_map, address); - check_cycles_int(native, address); + check_cycles_int(native, address, context->options); } void start_68k_context(m68k_context * context, uint32_t address) @@ -4468,6 +4469,58 @@ void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t n dst = add_ir(dst, 2, SCRATCH2, SZ_D); dst = jmp(dst, opts->write_16); + opts->handle_cycle_limit_int = dst; + dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); + uint8_t * do_int = dst+1; + dst = jcc(dst, CC_NC, dst+2); + dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); + uint8_t * skip_sync = dst+1; + dst = jcc(dst, CC_C, dst+2); + dst = call(dst, (uint8_t *)m68k_save_context); + dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); + dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); + dst = call(dst, (uint8_t *)sync_components); + dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = jmp(dst, (uint8_t *)m68k_load_context); + *skip_sync = dst - (skip_sync+1); + dst = retn(dst); + *do_int = dst - (do_int+1); + //set target cycle to sync cycle + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), LIMIT, SZ_D); + //swap USP and SSP if not already in supervisor mode + dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); + uint8_t *already_supervisor = dst+1; + dst = jcc(dst, CC_C, dst+2); + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH2, SZ_D); + dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); + dst = mov_rr(dst, SCRATCH2, opts->aregs[7], SZ_D); + *already_supervisor = dst - (already_supervisor+1); + //save PC + dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); + dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); + dst = call(dst, opts->write_32_lowfirst); + //save status register + dst = sub_ir(dst, 2, opts->aregs[7], SZ_D); + dst = call(dst, (uint8_t *)get_sr); + dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); + dst = call(dst, opts->write_16); + //update status register + dst = and_irdisp8(dst, 0xF8, CONTEXT, offsetof(m68k_context, status), SZ_B); + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_num), SCRATCH1, SZ_B); + dst = or_ir(dst, 0x20, SCRATCH1, SZ_B); + dst = or_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, status), SZ_B); + //calculate interrupt vector address + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_num), SCRATCH1, SZ_D); + dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, int_ack), SZ_W); + dst = shl_ir(dst, 2, SCRATCH1, SZ_D); + dst = add_ir(dst, 0x60, SCRATCH1, SZ_D); + dst = call(dst, opts->read_32); + dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); + dst = cycles(dst, 24); + //discard function return address + dst = pop_r(dst, SCRATCH2); + dst = jmp_r(dst, SCRATCH1); + opts->cur_code = dst; } |