Mercurial > repos > blastem
diff m68k_core_x86.c @ 1363:df6af7187b36
Fix to M68K interrupt latency for most instructions. Still needs some work for RAW_IMPL instructions besides move
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 19 May 2017 20:27:35 -0700 |
parents | 87bbc4bec958 |
children | eaca4443e831 |
line wrap: on
line diff
--- a/m68k_core_x86.c Sun May 14 12:07:39 2017 -0700 +++ b/m68k_core_x86.c Fri May 19 20:27:35 2017 -0700 @@ -350,12 +350,30 @@ 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 @@ } else { ea->base = reg; } - return; + return 0; } switch (op->addr_mode) { @@ -388,8 +406,9 @@ 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 @@ 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 @@ } ea->base = opts->gen.scratch1; } + return ret; } void check_user_mode_swap_ssp_usp(m68k_options *opts) @@ -540,7 +560,9 @@ 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 @@ 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);