diff options
author | Michael Pavone <pavone@retrodev.com> | 2017-05-19 20:27:35 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2017-05-19 20:27:35 -0700 |
commit | b3f9c8727f9890c1a3e3a9f64e86d58d5701f58c (patch) | |
tree | 3411d25ab9bdd532b4843208ed88087c60e3466d | |
parent | ec6165fd23f9994d2db087c6f0dc09afbebf5a73 (diff) |
Fix to M68K interrupt latency for most instructions. Still needs some work for RAW_IMPL instructions besides move
-rw-r--r-- | m68k_core.c | 8 | ||||
-rw-r--r-- | m68k_core.h | 1 | ||||
-rw-r--r-- | m68k_core_x86.c | 50 | ||||
-rw-r--r-- | m68k_internal.h | 3 |
4 files changed, 54 insertions, 8 deletions
diff --git a/m68k_core.c b/m68k_core.c index 1faa3c0..3ed8185 100644 --- a/m68k_core.c +++ b/m68k_core.c @@ -969,11 +969,15 @@ static void translate_m68k(m68k_context *context, m68kinst * inst) } host_ea src_op, dst_op; + uint8_t needs_int_latch = 0; if (inst->src.addr_mode != MODE_UNUSED) { - translate_m68k_op(inst, &src_op, opts, 0); + needs_int_latch |= translate_m68k_op(inst, &src_op, opts, 0); } if (inst->dst.addr_mode != MODE_UNUSED) { - translate_m68k_op(inst, &dst_op, opts, 1); + needs_int_latch |= translate_m68k_op(inst, &dst_op, opts, 1); + } + if (needs_int_latch) { + m68k_check_cycles_int_latch(opts); } if (info->itype == OP_FUNC) { info->impl.op(opts, inst, &src_op, &dst_op); diff --git a/m68k_core.h b/m68k_core.h index 7773d64..a18d706 100644 --- a/m68k_core.h +++ b/m68k_core.h @@ -48,6 +48,7 @@ typedef struct { code_ptr write_32_lowfirst; code_ptr write_32_highfirst; code_ptr do_sync; + code_ptr handle_int_latch; code_ptr trap; start_fun start_context; code_ptr retrans_stub; diff --git a/m68k_core_x86.c b/m68k_core_x86.c index fede6ff..07eb1e2 100644 --- a/m68k_core_x86.c +++ b/m68k_core_x86.c @@ -350,12 +350,30 @@ void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_ calc_index_disp8(opts, op, native_reg); } -void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst) +void m68k_check_cycles_int_latch(m68k_options *opts) +{ + code_info *code = &opts->gen.code; + uint8_t cc; + if (opts->gen.limit < 0) { + cmp_ir(code, 1, opts->gen.cycles, SZ_D); + cc = CC_NS; + } else { + cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); + cc = CC_A; + } + code_ptr jmp_off = code->cur+1; + jcc(code, cc, jmp_off+1); + call(code, opts->handle_int_latch); + *jmp_off = code->cur - (jmp_off+1); +} + +uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst) { code_info *code = &opts->gen.code; m68k_op_info *op = dst ? &inst->dst : &inst->src; int8_t reg = native_reg(op, opts); uint8_t sec_reg; + uint8_t ret = 1; int32_t dec_amount, inc_amount; if (reg >= 0) { ea->mode = MODE_REG_DIRECT; @@ -365,7 +383,7 @@ void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8 } else { ea->base = reg; } - return; + return 0; } switch (op->addr_mode) { @@ -388,8 +406,9 @@ void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8 ea->mode = MODE_REG_DIRECT; ea->base = opts->gen.scratch1; //we're explicitly handling the areg dest here, so we exit immediately - return; + return 0; } + ret = 0; break; case MODE_AREG_PREDEC: if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) { @@ -505,7 +524,7 @@ void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) { ea->disp |= 0xFFFF0000; } - return; + return inst->variant != VAR_QUICK; default: m68k_disasm(inst, disasm_buf); fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src"); @@ -519,6 +538,7 @@ void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8 } ea->base = opts->gen.scratch1; } + return ret; } void check_user_mode_swap_ssp_usp(m68k_options *opts) @@ -540,7 +560,9 @@ void translate_m68k_move(m68k_options * opts, m68kinst * inst) int32_t offset; int32_t inc_amount, dec_amount; host_ea src; - translate_m68k_op(inst, &src, opts, 0); + if (translate_m68k_op(inst, &src, opts, 0)) { + m68k_check_cycles_int_latch(opts); + } reg = native_reg(&(inst->dst), opts); if (inst->dst.addr_mode != MODE_AREG) { @@ -3085,6 +3107,24 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); jmp_r(code, opts->gen.scratch1); code->stack_off = tmp_stack_off; + + opts->handle_int_latch = code->cur; + cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); + code_ptr do_latch = code->cur + 1; + jcc(code, CC_NC, do_latch); + retn(code); + *do_latch = code->cur - (do_latch + 1); + cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); + do_latch = code->cur + 1; + jcc(code, CC_Z, do_latch); + retn(code); + *do_latch = code->cur - (do_latch + 1); + //store current interrupt number so it doesn't change before we start processing the vector + push_r(code, opts->gen.scratch1); + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); + pop_r(code, opts->gen.scratch1); + retn(code); opts->trap = code->cur; push_r(code, opts->gen.scratch2); diff --git a/m68k_internal.h b/m68k_internal.h index fbe26ce..4533de1 100644 --- a/m68k_internal.h +++ b/m68k_internal.h @@ -36,13 +36,14 @@ void m68k_set_last_prefetch(m68k_options *opts, uint32_t address); void translate_m68k_odd(m68k_options *opts, m68kinst *inst); void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst); void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr); +void m68k_check_cycles_int_latch(m68k_options *opts); +uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst); //functions implemented in m68k_core.c int8_t native_reg(m68k_op_info * op, m68k_options * opts); size_t dreg_offset(uint8_t reg); size_t areg_offset(uint8_t reg); size_t reg_offset(m68k_op_info *op); -void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst); void m68k_read_size(m68k_options *opts, uint8_t size); void m68k_write_size(m68k_options *opts, uint8_t size, uint8_t lowfirst); void m68k_save_result(m68kinst * inst, m68k_options * opts); |