Mercurial > repos > blastem
comparison m68k_core_x86.c @ 1989:0d87116630c7
Fix cycle timing of a number of 68K instructions
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 10 Jun 2020 19:08:41 -0700 |
parents | 35722beaf895 |
children | 8ee7ecbf3f21 |
comparison
equal
deleted
inserted
replaced
1986:a042e046f7f2 | 1989:0d87116630c7 |
---|---|
419 case MODE_AREG_PREDEC: | 419 case MODE_AREG_PREDEC: |
420 if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) { | 420 if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) { |
421 push_r(code, opts->gen.scratch1); | 421 push_r(code, opts->gen.scratch1); |
422 } | 422 } |
423 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 :1)); | 423 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 :1)); |
424 if (!dst) { | 424 if (!dst || ( |
425 inst->op != M68K_MOVE && inst->op != M68K_MOVEM | |
426 && inst->op != M68K_SUBX && inst->op != M68K_ADDX | |
427 && inst->op != M68K_ABCD && inst->op != M68K_SBCD | |
428 )) { | |
425 cycles(&opts->gen, PREDEC_PENALTY); | 429 cycles(&opts->gen, PREDEC_PENALTY); |
426 } | 430 } |
427 subi_areg(opts, dec_amount, op->params.regs.pri); | 431 subi_areg(opts, dec_amount, op->params.regs.pri); |
428 case MODE_AREG_INDIRECT: | 432 case MODE_AREG_INDIRECT: |
429 case MODE_AREG_POSTINC: | 433 case MODE_AREG_POSTINC: |
872 mov_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); | 876 mov_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); |
873 } | 877 } |
874 code_ptr end_off = code->cur+1; | 878 code_ptr end_off = code->cur+1; |
875 jmp(code, code->cur+2); | 879 jmp(code, code->cur+2); |
876 *true_off = code->cur - (true_off+1); | 880 *true_off = code->cur - (true_off+1); |
877 cycles(&opts->gen, 6); | 881 cycles(&opts->gen, inst->dst.addr_mode == MODE_REG ? 6 : 4); |
878 if (dst_op.mode == MODE_REG_DIRECT) { | 882 if (dst_op.mode == MODE_REG_DIRECT) { |
879 mov_ir(code, 0xFF, dst_op.base, SZ_B); | 883 mov_ir(code, 0xFF, dst_op.base, SZ_B); |
880 } else { | 884 } else { |
881 mov_irdisp(code, 0xFF, dst_op.base, dst_op.disp, SZ_B); | 885 mov_irdisp(code, 0xFF, dst_op.base, dst_op.disp, SZ_B); |
882 } | 886 } |
1188 } | 1192 } |
1189 | 1193 |
1190 void translate_m68k_reset(m68k_options *opts, m68kinst *inst) | 1194 void translate_m68k_reset(m68k_options *opts, m68kinst *inst) |
1191 { | 1195 { |
1192 code_info *code = &opts->gen.code; | 1196 code_info *code = &opts->gen.code; |
1193 //RESET instructions take a long time to give peripherals time to reset themselves | |
1194 cycles(&opts->gen, 132); | |
1195 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR); | 1197 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR); |
1196 cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR); | 1198 cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR); |
1197 code_ptr no_reset_handler = code->cur + 1; | 1199 code_ptr no_reset_handler = code->cur + 1; |
1198 jcc(code, CC_Z, code->cur+2); | 1200 jcc(code, CC_Z, code->cur+2); |
1199 call(code, opts->gen.save_context); | 1201 call(code, opts->gen.save_context); |
1200 call_args_r(code, opts->gen.scratch1, 1, opts->gen.context_reg); | 1202 call_args_r(code, opts->gen.scratch1, 1, opts->gen.context_reg); |
1201 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); | 1203 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); |
1202 call(code, opts->gen.load_context); | 1204 call(code, opts->gen.load_context); |
1203 *no_reset_handler = code->cur - (no_reset_handler + 1); | 1205 *no_reset_handler = code->cur - (no_reset_handler + 1); |
1206 //RESET instructions take a long time to give peripherals time to reset themselves | |
1207 cycles(&opts->gen, 132); | |
1204 } | 1208 } |
1205 | 1209 |
1206 void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t size) | 1210 void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t size) |
1207 { | 1211 { |
1208 switch (inst->op) | 1212 switch (inst->op) |
1307 code_info *code = &opts->gen.code; | 1311 code_info *code = &opts->gen.code; |
1308 uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; | 1312 uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; |
1309 | 1313 |
1310 uint32_t numcycles; | 1314 uint32_t numcycles; |
1311 if ((inst->op == M68K_ADDX || inst->op == M68K_SUBX) && inst->src.addr_mode != MODE_REG) { | 1315 if ((inst->op == M68K_ADDX || inst->op == M68K_SUBX) && inst->src.addr_mode != MODE_REG) { |
1312 numcycles = 6; | 1316 numcycles = 4; |
1313 } else if (size == OPSIZE_LONG) { | 1317 } else if (size == OPSIZE_LONG) { |
1314 if (inst->op == M68K_CMP) { | 1318 if (inst->op == M68K_CMP) { |
1319 numcycles = inst->src.addr_mode > MODE_AREG && inst->dst.addr_mode > MODE_AREG ? 4 : 6; | |
1320 } else if (inst->op == M68K_AND && inst->variant == VAR_IMMEDIATE && inst->dst.addr_mode == MODE_REG) { | |
1315 numcycles = 6; | 1321 numcycles = 6; |
1316 } else if (inst->op == M68K_AND && inst->variant == VAR_IMMEDIATE) { | 1322 } else if (inst->dst.addr_mode == MODE_REG) { |
1317 numcycles = 6; | |
1318 } else if (inst->dst.addr_mode <= MODE_AREG) { | |
1319 numcycles = inst->src.addr_mode <= MODE_AREG || inst->src.addr_mode == MODE_IMMEDIATE ? 8 : 6; | 1323 numcycles = inst->src.addr_mode <= MODE_AREG || inst->src.addr_mode == MODE_IMMEDIATE ? 8 : 6; |
1324 } else if (inst->dst.addr_mode == MODE_AREG) { | |
1325 numcycles = numcycles = inst->src.addr_mode <= MODE_AREG || inst->src.addr_mode == MODE_IMMEDIATE | |
1326 || inst->extra.size == OPSIZE_WORD ? 8 : 6; | |
1320 } else { | 1327 } else { |
1321 numcycles = 4; | 1328 numcycles = 4; |
1322 } | 1329 } |
1323 } else { | 1330 } else { |
1324 numcycles = 4; | 1331 numcycles = 4; |
1491 } | 1498 } |
1492 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) { | 1499 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) { |
1493 //destination is in memory so we need to preserve scratch2 for the write at the end | 1500 //destination is in memory so we need to preserve scratch2 for the write at the end |
1494 push_r(code, opts->gen.scratch2); | 1501 push_r(code, opts->gen.scratch2); |
1495 } | 1502 } |
1496 //MC68000 User's Manual suggests NBCD hides the 2 cycle penalty during the write cycle somehow | 1503 |
1497 cycles(&opts->gen, inst->op == M68K_NBCD && inst->dst.addr_mode != MODE_REG_DIRECT ? BUS : BUS + 2); | 1504 //reg to reg takes 6 cycles, mem to mem is 4 cycles + all the operand fetch/writing (including 2 cycle predec penalty for first operand) |
1505 cycles(&opts->gen, inst->dst.addr_mode != MODE_REG ? BUS : BUS + 2); | |
1498 uint8_t other_reg; | 1506 uint8_t other_reg; |
1499 //WARNING: This may need adjustment if register assignments change | 1507 //WARNING: This may need adjustment if register assignments change |
1500 if (opts->gen.scratch2 > RBX) { | 1508 if (opts->gen.scratch2 > RBX) { |
1501 other_reg = RAX; | 1509 other_reg = RAX; |
1502 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); | 1510 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); |
2066 } | 2074 } |
2067 | 2075 |
2068 void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2076 void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2069 { | 2077 { |
2070 code_info *code = &opts->gen.code; | 2078 code_info *code = &opts->gen.code; |
2071 cycles(&opts->gen, BUS); | 2079 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG && inst->dst.addr_mode == MODE_REG ? BUS+2 : BUS); |
2072 if (dst_op->mode == MODE_REG_DIRECT) { | 2080 if (dst_op->mode == MODE_REG_DIRECT) { |
2073 if (dst_op->base == opts->gen.scratch1) { | 2081 if (dst_op->base == opts->gen.scratch1) { |
2074 push_r(code, opts->gen.scratch2); | 2082 push_r(code, opts->gen.scratch2); |
2075 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size); | 2083 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size); |
2076 flag_to_carry(opts, FLAG_X); | 2084 flag_to_carry(opts, FLAG_X); |
2132 } else { | 2140 } else { |
2133 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 2141 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
2134 } | 2142 } |
2135 update_flags(opts, init_flags); | 2143 update_flags(opts, init_flags); |
2136 } else { | 2144 } else { |
2145 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); | |
2137 if (src_op->mode == MODE_REG_DIRECT) { | 2146 if (src_op->mode == MODE_REG_DIRECT) { |
2138 if (src_op->base != opts->gen.scratch1) { | 2147 if (src_op->base != opts->gen.scratch1) { |
2139 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); | 2148 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); |
2140 } | 2149 } |
2141 } else { | 2150 } else { |
2439 } | 2448 } |
2440 | 2449 |
2441 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2450 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2442 { | 2451 { |
2443 code_info *code = &opts->gen.code; | 2452 code_info *code = &opts->gen.code; |
2444 cycles(&opts->gen, inst->dst.addr_mode == MODE_REG_DIRECT ? BUS+2 : BUS); | 2453 cycles(&opts->gen, inst->dst.addr_mode == MODE_REG ? BUS+2 : BUS); |
2445 call(code, opts->get_sr); | 2454 call(code, opts->get_sr); |
2446 if (dst_op->mode == MODE_REG_DIRECT) { | 2455 if (dst_op->mode == MODE_REG_DIRECT) { |
2447 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); | 2456 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); |
2448 } else { | 2457 } else { |
2449 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); | 2458 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); |