Mercurial > repos > blastem
comparison m68k_core_x86.c @ 2053:3414a4423de1 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 15 Jan 2022 13:15:21 -0800 |
parents | 0d87116630c7 |
children | 8ee7ecbf3f21 |
comparison
equal
deleted
inserted
replaced
1692:5dacaef602a7 | 2053:3414a4423de1 |
---|---|
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->op == M68K_ADD && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && inst->variant == VAR_QUICK) { | |
1319 numcycles = 4; | |
1320 } else if (inst->dst.addr_mode <= MODE_AREG) { | |
1321 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; | |
1322 } else { | 1327 } else { |
1323 numcycles = 4; | 1328 numcycles = 4; |
1324 } | 1329 } |
1325 } else { | 1330 } else { |
1326 numcycles = 4; | 1331 numcycles = 4; |
1493 } | 1498 } |
1494 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) { |
1495 //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 |
1496 push_r(code, opts->gen.scratch2); | 1501 push_r(code, opts->gen.scratch2); |
1497 } | 1502 } |
1498 //MC68000 User's Manual suggests NBCD hides the 2 cycle penalty during the write cycle somehow | 1503 |
1499 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); | |
1500 uint8_t other_reg; | 1506 uint8_t other_reg; |
1501 //WARNING: This may need adjustment if register assignments change | 1507 //WARNING: This may need adjustment if register assignments change |
1502 if (opts->gen.scratch2 > RBX) { | 1508 if (opts->gen.scratch2 > RBX) { |
1503 other_reg = RAX; | 1509 other_reg = RAX; |
1504 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); | 1510 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); |
2068 } | 2074 } |
2069 | 2075 |
2070 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) |
2071 { | 2077 { |
2072 code_info *code = &opts->gen.code; | 2078 code_info *code = &opts->gen.code; |
2073 cycles(&opts->gen, BUS); | 2079 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG && inst->dst.addr_mode == MODE_REG ? BUS+2 : BUS); |
2074 if (dst_op->mode == MODE_REG_DIRECT) { | 2080 if (dst_op->mode == MODE_REG_DIRECT) { |
2075 if (dst_op->base == opts->gen.scratch1) { | 2081 if (dst_op->base == opts->gen.scratch1) { |
2076 push_r(code, opts->gen.scratch2); | 2082 push_r(code, opts->gen.scratch2); |
2077 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); |
2078 flag_to_carry(opts, FLAG_X); | 2084 flag_to_carry(opts, FLAG_X); |
2134 } else { | 2140 } else { |
2135 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); |
2136 } | 2142 } |
2137 update_flags(opts, init_flags); | 2143 update_flags(opts, init_flags); |
2138 } else { | 2144 } else { |
2145 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); | |
2139 if (src_op->mode == MODE_REG_DIRECT) { | 2146 if (src_op->mode == MODE_REG_DIRECT) { |
2140 if (src_op->base != opts->gen.scratch1) { | 2147 if (src_op->base != opts->gen.scratch1) { |
2141 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); | 2148 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); |
2142 } | 2149 } |
2143 } else { | 2150 } else { |
2441 } | 2448 } |
2442 | 2449 |
2443 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) |
2444 { | 2451 { |
2445 code_info *code = &opts->gen.code; | 2452 code_info *code = &opts->gen.code; |
2446 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); |
2447 call(code, opts->get_sr); | 2454 call(code, opts->get_sr); |
2448 if (dst_op->mode == MODE_REG_DIRECT) { | 2455 if (dst_op->mode == MODE_REG_DIRECT) { |
2449 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); | 2456 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); |
2450 } else { | 2457 } else { |
2451 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); |
2656 retn(code); | 2663 retn(code); |
2657 | 2664 |
2658 opts->start_context = (start_fun)code->cur; | 2665 opts->start_context = (start_fun)code->cur; |
2659 save_callee_save_regs(code); | 2666 save_callee_save_regs(code); |
2660 #ifdef X86_64 | 2667 #ifdef X86_64 |
2661 if (opts->gen.scratch2 != RDI) { | 2668 if (opts->gen.scratch2 != FIRST_ARG_REG) { |
2662 mov_rr(code, RDI, opts->gen.scratch2, SZ_PTR); | 2669 mov_rr(code, FIRST_ARG_REG, opts->gen.scratch2, SZ_PTR); |
2670 } | |
2671 if (opts->gen.context_reg != SECOND_ARG_REG) { | |
2672 mov_rr(code, SECOND_ARG_REG, opts->gen.context_reg, SZ_PTR); | |
2663 } | 2673 } |
2664 #else | 2674 #else |
2665 mov_rdispr(code, RSP, 20, opts->gen.scratch2, SZ_D); | 2675 mov_rdispr(code, RSP, 20, opts->gen.scratch2, SZ_D); |
2666 mov_rdispr(code, RSP, 24, opts->gen.context_reg, SZ_D); | 2676 mov_rdispr(code, RSP, 24, opts->gen.context_reg, SZ_D); |
2667 #endif | 2677 #endif |