Mercurial > repos > blastem
diff m68k_to_x86.c @ 347:b24556b45d1e
Generate handle_cycle_limit_int at runtime so it can refer to the runtime generated memory map functions
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 21 May 2013 00:56:56 -0700 |
parents | 467bfa17004a |
children | 3923dbc2dcc4 |
line wrap: on
line diff
--- a/m68k_to_x86.c Sun May 19 18:40:34 2013 -0700 +++ b/m68k_to_x86.c Tue May 21 00:56:56 2013 -0700 @@ -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 @@ 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 * 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 @@ 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 @@ 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 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 @@ 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; }