Mercurial > repos > blastem
comparison m68k_core_x86.c @ 1692:5dacaef602a7 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 05 Jan 2019 00:58:08 -0800 |
parents | 15116d4fdf40 |
children | 37afb9cf58be |
comparison
equal
deleted
inserted
replaced
1504:95b3a1a8b26c | 1692:5dacaef602a7 |
---|---|
740 | 740 |
741 //add cycles for prefetch | 741 //add cycles for prefetch |
742 cycles(&opts->gen, BUS); | 742 cycles(&opts->gen, BUS); |
743 } | 743 } |
744 | 744 |
745 void translate_m68k_clr(m68k_options * opts, m68kinst * inst) | |
746 { | |
747 code_info *code = &opts->gen.code; | |
748 update_flags(opts, N0|V0|C0|Z1); | |
749 int8_t reg = native_reg(&(inst->dst), opts); | |
750 if (reg >= 0) { | |
751 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); | |
752 xor_rr(code, reg, reg, inst->extra.size); | |
753 return; | |
754 } | |
755 host_ea dst_op; | |
756 //TODO: fix timing | |
757 translate_m68k_op(inst, &dst_op, opts, 1); | |
758 if (dst_op.mode == MODE_REG_DIRECT) { | |
759 xor_rr(code, dst_op.base, dst_op.base, inst->extra.size); | |
760 } else { | |
761 mov_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); | |
762 } | |
763 m68k_save_result(inst, opts); | |
764 } | |
765 | |
766 void translate_m68k_ext(m68k_options * opts, m68kinst * inst) | 745 void translate_m68k_ext(m68k_options * opts, m68kinst * inst) |
767 { | 746 { |
768 code_info *code = &opts->gen.code; | 747 code_info *code = &opts->gen.code; |
769 host_ea dst_op; | 748 host_ea dst_op; |
770 uint8_t dst_size = inst->extra.size; | 749 uint8_t dst_size = inst->extra.size; |
778 cmp_ir(code, 0, opts->gen.scratch1, dst_size); | 757 cmp_ir(code, 0, opts->gen.scratch1, dst_size); |
779 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size); | 758 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size); |
780 } | 759 } |
781 inst->extra.size = dst_size; | 760 inst->extra.size = dst_size; |
782 update_flags(opts, N|V0|C0|Z); | 761 update_flags(opts, N|V0|C0|Z); |
762 cycles(&opts->gen, BUS); | |
783 //M68K EXT only operates on registers so no need for a call to save result here | 763 //M68K EXT only operates on registers so no need for a call to save result here |
784 } | 764 } |
785 | 765 |
786 uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) | 766 uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) |
787 { | 767 { |
1208 } | 1188 } |
1209 | 1189 |
1210 void translate_m68k_reset(m68k_options *opts, m68kinst *inst) | 1190 void translate_m68k_reset(m68k_options *opts, m68kinst *inst) |
1211 { | 1191 { |
1212 code_info *code = &opts->gen.code; | 1192 code_info *code = &opts->gen.code; |
1213 cycles(&opts->gen, BUS); | 1193 //RESET instructions take a long time to give peripherals time to reset themselves |
1194 cycles(&opts->gen, 132); | |
1214 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR); | 1195 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR); |
1215 cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR); | 1196 cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR); |
1216 code_ptr no_reset_handler = code->cur + 1; | 1197 code_ptr no_reset_handler = code->cur + 1; |
1217 jcc(code, CC_Z, code->cur+2); | 1198 jcc(code, CC_Z, code->cur+2); |
1218 call(code, opts->gen.save_context); | 1199 call(code, opts->gen.save_context); |
1435 | 1416 |
1436 void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size) | 1417 void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size) |
1437 { | 1418 { |
1438 switch(inst->op) | 1419 switch(inst->op) |
1439 { | 1420 { |
1421 case M68K_CLR: xor_rr(code, dst, dst, size); break; | |
1440 case M68K_NEG: neg_r(code, dst, size); break; | 1422 case M68K_NEG: neg_r(code, dst, size); break; |
1441 case M68K_NOT: not_r(code, dst, size); cmp_ir(code, 0, dst, size); break; | 1423 case M68K_NOT: not_r(code, dst, size); cmp_ir(code, 0, dst, size); break; |
1442 case M68K_ROL: rol_clr(code, dst, size); break; | 1424 case M68K_ROL: rol_clr(code, dst, size); break; |
1443 case M68K_ROR: ror_clr(code, dst, size); break; | 1425 case M68K_ROR: ror_clr(code, dst, size); break; |
1444 case M68K_ROXL: rcl_clr(code, dst, size); break; | 1426 case M68K_ROXL: rcl_clr(code, dst, size); break; |
1450 | 1432 |
1451 void op_rdisp(code_info *code, m68kinst *inst, uint8_t dst, int32_t disp, uint8_t size) | 1433 void op_rdisp(code_info *code, m68kinst *inst, uint8_t dst, int32_t disp, uint8_t size) |
1452 { | 1434 { |
1453 switch(inst->op) | 1435 switch(inst->op) |
1454 { | 1436 { |
1437 case M68K_CLR: mov_irdisp(code, 0, dst, disp, size); break; | |
1455 case M68K_NEG: neg_rdisp(code, dst, disp, size); break; | 1438 case M68K_NEG: neg_rdisp(code, dst, disp, size); break; |
1456 case M68K_NOT: not_rdisp(code, dst, disp, size); cmp_irdisp(code, 0, dst, disp, size); break; | 1439 case M68K_NOT: not_rdisp(code, dst, disp, size); cmp_irdisp(code, 0, dst, disp, size); break; |
1457 case M68K_ROL: rol_clrdisp(code, dst, disp, size); break; | 1440 case M68K_ROL: rol_clrdisp(code, dst, disp, size); break; |
1458 case M68K_ROR: ror_clrdisp(code, dst, disp, size); break; | 1441 case M68K_ROR: ror_clrdisp(code, dst, disp, size); break; |
1459 case M68K_ROXL: rcl_clrdisp(code, dst, disp, size); break; | 1442 case M68K_ROXL: rcl_clrdisp(code, dst, disp, size); break; |
1464 } | 1447 } |
1465 | 1448 |
1466 void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, host_ea *dst_op) | 1449 void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, host_ea *dst_op) |
1467 { | 1450 { |
1468 code_info *code = &opts->gen.code; | 1451 code_info *code = &opts->gen.code; |
1469 cycles(&opts->gen, BUS); | 1452 uint32_t num_cycles = BUS; |
1453 if (inst->extra.size == OPSIZE_LONG && (inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)) { | |
1454 num_cycles += 2; | |
1455 } | |
1456 cycles(&opts->gen, num_cycles); | |
1470 if (dst_op->mode == MODE_REG_DIRECT) { | 1457 if (dst_op->mode == MODE_REG_DIRECT) { |
1471 op_r(code, inst, dst_op->base, inst->extra.size); | 1458 op_r(code, inst, dst_op->base, inst->extra.size); |
1472 } else { | 1459 } else { |
1473 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size); | 1460 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size); |
1474 } | 1461 } |
1506 } | 1493 } |
1507 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) { | 1494 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) { |
1508 //destination is in memory so we need to preserve scratch2 for the write at the end | 1495 //destination is in memory so we need to preserve scratch2 for the write at the end |
1509 push_r(code, opts->gen.scratch2); | 1496 push_r(code, opts->gen.scratch2); |
1510 } | 1497 } |
1498 //MC68000 User's Manual suggests NBCD hides the 2 cycle penalty during the write cycle somehow | |
1499 cycles(&opts->gen, inst->op == M68K_NBCD && inst->dst.addr_mode != MODE_REG_DIRECT ? BUS : BUS + 2); | |
1511 uint8_t other_reg; | 1500 uint8_t other_reg; |
1512 //WARNING: This may need adjustment if register assignments change | 1501 //WARNING: This may need adjustment if register assignments change |
1513 if (opts->gen.scratch2 > RBX) { | 1502 if (opts->gen.scratch2 > RBX) { |
1514 other_reg = RAX; | 1503 other_reg = RAX; |
1515 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); | 1504 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); |
2363 //leave supervisor mode | 2352 //leave supervisor mode |
2364 swap_ssp_usp(opts); | 2353 swap_ssp_usp(opts); |
2365 } | 2354 } |
2366 code_ptr loop_top = code->cur; | 2355 code_ptr loop_top = code->cur; |
2367 call(code, opts->do_sync); | 2356 call(code, opts->do_sync); |
2368 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); | 2357 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); |
2369 code_ptr normal_cycle_up = code->cur + 1; | 2358 code_ptr normal_cycle_up = code->cur + 1; |
2370 jcc(code, CC_A, code->cur + 2); | 2359 jcc(code, CC_A, code->cur + 2); |
2371 cycles(&opts->gen, BUS); | 2360 cycles(&opts->gen, BUS); |
2372 code_ptr after_cycle_up = code->cur + 1; | 2361 code_ptr after_cycle_up = code->cur + 1; |
2373 jmp(code, code->cur + 2); | 2362 jmp(code, code->cur + 2); |
2452 } | 2441 } |
2453 | 2442 |
2454 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2443 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2455 { | 2444 { |
2456 code_info *code = &opts->gen.code; | 2445 code_info *code = &opts->gen.code; |
2446 cycles(&opts->gen, inst->dst.addr_mode == MODE_REG_DIRECT ? BUS+2 : BUS); | |
2457 call(code, opts->get_sr); | 2447 call(code, opts->get_sr); |
2458 if (dst_op->mode == MODE_REG_DIRECT) { | 2448 if (dst_op->mode == MODE_REG_DIRECT) { |
2459 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); | 2449 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); |
2460 } else { | 2450 } else { |
2461 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); | 2451 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); |