# HG changeset patch # User Michael Pavone # Date 1662364143 25200 # Node ID d8b0244101c4c6969db909c4477e6fb0b72cbe08 # Parent 1cccc57c069ad2baae4961d9c8241edd9cda7fb2 Fix bad 68K instruction timings revealed by Ti_'s test ROM, except those that involve exception timing diff -r 1cccc57c069a -r d8b0244101c4 68kinst.c --- a/68kinst.c Sun Sep 04 23:29:37 2022 -0700 +++ b/68kinst.c Mon Sep 05 00:49:03 2022 -0700 @@ -1154,7 +1154,6 @@ #endif } else { decoded->op = M68K_SCC; - decoded->extra.cond = (opcode >> 8) & 0xF; address = m68k_decode_op(opcode, address, fetch, data, OPSIZE_BYTE, &(decoded->dst)); if (address == INVALID_ADDRESS || !m68k_valid_immed_limited_dst(&decoded->dst)) { decoded->op = M68K_INVALID; diff -r 1cccc57c069a -r d8b0244101c4 m68k_core.c --- a/m68k_core.c Sun Sep 04 23:29:37 2022 -0700 +++ b/m68k_core.c Mon Sep 05 00:49:03 2022 -0700 @@ -231,7 +231,7 @@ jmp_r(code, opts->gen.scratch1); break; case MODE_AREG_DISPLACE: - cycles(&opts->gen, BUS*2); + cycles(&opts->gen, BUS*2 + 2); if (is_jsr) { push_const(opts, inst->address+4); } @@ -240,7 +240,7 @@ jmp_r(code, opts->gen.scratch1); break; case MODE_AREG_INDEX_DISP8: - cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct + cycles(&opts->gen, BUS*3 + 2); if (is_jsr) { push_const(opts, inst->address+4); } @@ -257,7 +257,7 @@ jump_m68k_abs(opts, inst->src.params.regs.displacement + inst->address + 2); break; case MODE_PC_INDEX_DISP8: - cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct + cycles(&opts->gen, BUS*3 + 2); if (is_jsr) { push_const(opts, inst->address+4); } @@ -332,6 +332,7 @@ areg_to_native(opts, 7, opts->gen.scratch1); call(code, opts->read_32); addi_areg(opts, 4, 7); + cycles(&opts->gen, 2*BUS); //Get native address and jump to it call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); diff -r 1cccc57c069a -r d8b0244101c4 m68k_core_x86.c --- a/m68k_core_x86.c Sun Sep 04 23:29:37 2022 -0700 +++ b/m68k_core_x86.c Mon Sep 05 00:49:03 2022 -0700 @@ -854,7 +854,7 @@ inst->extra.size = OPSIZE_BYTE; translate_m68k_op(inst, &dst_op, opts, 1); if (cond == COND_TRUE || cond == COND_FALSE) { - if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) { + if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && cond == COND_TRUE) { cycles(&opts->gen, 6); } else { cycles(&opts->gen, BUS); @@ -1317,8 +1317,6 @@ } else if (size == OPSIZE_LONG) { if (inst->op == M68K_CMP) { numcycles = inst->src.addr_mode > MODE_AREG && inst->dst.addr_mode > MODE_AREG ? 4 : 6; - } else if (inst->op == M68K_AND && inst->variant == VAR_IMMEDIATE && inst->dst.addr_mode == MODE_REG) { - numcycles = 6; } else if (inst->dst.addr_mode == MODE_REG) { numcycles = inst->src.addr_mode <= MODE_AREG || inst->src.addr_mode == MODE_IMMEDIATE ? 8 : 6; } else if (inst->dst.addr_mode == MODE_AREG) { @@ -1616,12 +1614,15 @@ void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) { code_info *code = &opts->gen.code; - cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : ( - inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) + cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? (dst_op->mode == MODE_IMMED ? 6 : 4) : ( + inst->op == M68K_BCLR ? 8 : 6) ); if (src_op->mode == MODE_IMMED) { if (inst->extra.size == OPSIZE_BYTE) { src_op->disp &= 0x7; + } else if (inst->op != M68K_BTST && src_op->disp > 15) { + //bit operations that need to save the result have a 2 cycle penalty when operating on the upper word + cycles(&opts->gen, 2); } if (dst_op->mode == MODE_REG_DIRECT) { op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size); @@ -1669,6 +1670,19 @@ and_ir(code, 7, src_op->base, SZ_D); size = SZ_D; } + if (inst->op != M68K_BTST && inst->extra.size != OPSIZE_BYTE) { + //bit operations that need to save the result have a 2 cycle penalty when operating on the upper word + + if (src_op->mode == MODE_REG_DISPLACE8) { + cmp_irdisp(code, 16, src_op->base, src_op->disp, SZ_B); + } else { + cmp_ir(code, 16, src_op->base, SZ_B); + } + code_ptr jmp_off = code->cur + 1; + jcc(code, CC_C, jmp_off + 1); + cycles(&opts->gen, 2); + *jmp_off = code->cur - (jmp_off + 1); + } if (dst_op->mode == MODE_IMMED) { dst_op->base = src_op->base == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1; mov_ir(code, dst_op->disp, dst_op->base, SZ_B); @@ -1795,7 +1809,7 @@ context->flags[FLAG_V] = 1; context->flags[FLAG_N] = 1; context->flags[FLAG_Z] = 0; - cycles += 2; + cycles += 4; context->current_cycle += cycles * context->options->gen.clock_divider; return orig_dividend; }