Mercurial > repos > blastem
comparison m68k_to_x86.c @ 207:c82f65a87a53
Fix overflow flag on ASL
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 25 Jan 2013 18:39:22 -0800 |
parents | 7c227a8ec53d |
children | 3457dc6fd558 |
comparison
equal
deleted
inserted
replaced
206:807ca611b561 | 207:c82f65a87a53 |
---|---|
90 return offsetof(m68k_context, aregs) + sizeof(uint32_t) * op->params.regs.pri; | 90 return offsetof(m68k_context, aregs) + sizeof(uint32_t) * op->params.regs.pri; |
91 } | 91 } |
92 | 92 |
93 void print_regs_exit(m68k_context * context) | 93 void print_regs_exit(m68k_context * context) |
94 { | 94 { |
95 printf("XNVZC\n%d%d%d%d%d\n", context->flags[0], context->flags[1], context->flags[2], context->flags[3], context->flags[4]); | 95 printf("XNZVC\n%d%d%d%d%d\n", context->flags[0], context->flags[1], context->flags[2], context->flags[3], context->flags[4]); |
96 for (int i = 0; i < 8; i++) { | 96 for (int i = 0; i < 8; i++) { |
97 printf("d%d: %X\n", i, context->dregs[i]); | 97 printf("d%d: %X\n", i, context->dregs[i]); |
98 } | 98 } |
99 for (int i = 0; i < 8; i++) { | 99 for (int i = 0; i < 8; i++) { |
100 printf("a%d: %X\n", i, context->aregs[i]); | 100 printf("a%d: %X\n", i, context->aregs[i]); |
2617 typedef uint8_t * (*shift_clrdisp8_t)(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size); | 2617 typedef uint8_t * (*shift_clrdisp8_t)(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size); |
2618 | 2618 |
2619 uint8_t * translate_shift(uint8_t * dst, m68kinst * inst, x86_ea *src_op, x86_ea * dst_op, x86_68k_options * opts, shift_ir_t shift_ir, shift_irdisp8_t shift_irdisp8, shift_clr_t shift_clr, shift_clrdisp8_t shift_clrdisp8, shift_ir_t special, shift_irdisp8_t special_disp8) | 2619 uint8_t * translate_shift(uint8_t * dst, m68kinst * inst, x86_ea *src_op, x86_ea * dst_op, x86_68k_options * opts, shift_ir_t shift_ir, shift_irdisp8_t shift_irdisp8, shift_clr_t shift_clr, shift_clrdisp8_t shift_clrdisp8, shift_ir_t special, shift_irdisp8_t special_disp8) |
2620 { | 2620 { |
2621 uint8_t * end_off = NULL; | 2621 uint8_t * end_off = NULL; |
2622 uint8_t * nz_off = NULL; | |
2623 uint8_t * z_off = NULL; | |
2622 if (inst->src.addr_mode == MODE_UNUSED) { | 2624 if (inst->src.addr_mode == MODE_UNUSED) { |
2623 dst = cycles(dst, BUS); | 2625 dst = cycles(dst, BUS); |
2624 //Memory shift | 2626 //Memory shift |
2625 dst = shift_ir(dst, 1, dst_op->base, SZ_W); | 2627 dst = shift_ir(dst, 1, dst_op->base, SZ_W); |
2626 } else { | 2628 } else { |
2627 dst = cycles(dst, inst->extra.size == OPSIZE_LONG ? 8 : 6); | 2629 dst = cycles(dst, inst->extra.size == OPSIZE_LONG ? 8 : 6); |
2628 if (src_op->mode == MODE_IMMED) { | 2630 if (src_op->mode == MODE_IMMED) { |
2629 if (dst_op->mode == MODE_REG_DIRECT) { | 2631 if (src_op->disp != 1 && inst->op == M68K_ASL) { |
2630 dst = shift_ir(dst, src_op->disp, dst_op->base, inst->extra.size); | 2632 dst = mov_ir(dst, 0, FLAG_V, SZ_B); |
2631 } else { | 2633 for (int i = 0; i < src_op->disp; i++) { |
2632 dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 2634 if (dst_op->mode == MODE_REG_DIRECT) { |
2635 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | |
2636 } else { | |
2637 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | |
2638 } | |
2639 //dst = setcc_r(dst, CC_O, FLAG_V); | |
2640 dst = jcc(dst, CC_NO, dst+4); | |
2641 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | |
2642 } | |
2643 } else { | |
2644 if (dst_op->mode == MODE_REG_DIRECT) { | |
2645 dst = shift_ir(dst, src_op->disp, dst_op->base, inst->extra.size); | |
2646 } else { | |
2647 dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | |
2648 } | |
2633 } | 2649 } |
2634 } else { | 2650 } else { |
2635 if (src_op->base != RCX) { | 2651 if (src_op->base != RCX) { |
2636 if (src_op->mode == MODE_REG_DIRECT) { | 2652 if (src_op->mode == MODE_REG_DIRECT) { |
2637 dst = mov_rr(dst, src_op->base, RCX, SZ_B); | 2653 dst = mov_rr(dst, src_op->base, RCX, SZ_B); |
2638 } else { | 2654 } else { |
2639 dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); | 2655 dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); |
2640 } | 2656 } |
2657 | |
2641 } | 2658 } |
2642 dst = and_ir(dst, 63, RCX, SZ_D); | 2659 dst = and_ir(dst, 63, RCX, SZ_D); |
2660 nz_off = dst+1; | |
2661 dst = jcc(dst, CC_NZ, dst+2); | |
2662 //Flag behavior for shift count of 0 is different for x86 than 68K | |
2663 if (dst_op->mode == MODE_REG_DIRECT) { | |
2664 dst = cmp_ir(dst, 0, dst_op->base, inst->extra.size); | |
2665 } else { | |
2666 dst = cmp_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | |
2667 } | |
2668 dst = setcc_r(dst, CC_Z, FLAG_Z); | |
2669 dst = setcc_r(dst, CC_S, FLAG_N); | |
2670 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | |
2671 //For other instructions, this flag will be set below | |
2672 if (inst->op == M68K_ASL) { | |
2673 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | |
2674 } | |
2675 z_off = dst+1; | |
2676 dst = jmp(dst, dst+2); | |
2677 *nz_off = dst - (nz_off + 1); | |
2643 //add 2 cycles for every bit shifted | 2678 //add 2 cycles for every bit shifted |
2644 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2679 dst = add_rr(dst, RCX, CYCLES, SZ_D); |
2645 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2680 dst = add_rr(dst, RCX, CYCLES, SZ_D); |
2646 //x86 shifts modulo 32 for operand sizes less than 64-bits | 2681 if (inst->op == M68K_ASL) { |
2647 //but M68K shifts modulo 64, so we need to check for large shifts here | 2682 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB |
2648 dst = cmp_ir(dst, 32, RCX, SZ_B); | 2683 //Easiest way to deal with this is to shift one bit at a time |
2649 uint8_t * norm_shift_off = dst + 1; | 2684 dst = mov_ir(dst, 0, FLAG_V, SZ_B); |
2650 dst = jcc(dst, CC_L, dst+2); | 2685 uint8_t * loop_start = dst; |
2651 if (special) { | 2686 if (dst_op->mode == MODE_REG_DIRECT) { |
2652 if (inst->extra.size == OPSIZE_LONG) { | 2687 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2653 uint8_t * neq_32_off = dst + 1; | 2688 } else { |
2654 dst = jcc(dst, CC_NZ, dst+2); | 2689 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2690 } | |
2691 //dst = setcc_r(dst, CC_O, FLAG_V); | |
2692 dst = jcc(dst, CC_NO, dst+4); | |
2693 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | |
2694 dst = loop(dst, loop_start); | |
2695 } else { | |
2696 //x86 shifts modulo 32 for operand sizes less than 64-bits | |
2697 //but M68K shifts modulo 64, so we need to check for large shifts here | |
2698 dst = cmp_ir(dst, 32, RCX, SZ_B); | |
2699 uint8_t * norm_shift_off = dst + 1; | |
2700 dst = jcc(dst, CC_L, dst+2); | |
2701 if (special) { | |
2702 if (inst->extra.size == OPSIZE_LONG) { | |
2703 uint8_t * neq_32_off = dst + 1; | |
2704 dst = jcc(dst, CC_NZ, dst+2); | |
2655 | 2705 |
2656 //set the carry bit to the lsb | 2706 //set the carry bit to the lsb |
2707 if (dst_op->mode == MODE_REG_DIRECT) { | |
2708 dst = special(dst, 1, dst_op->base, SZ_D); | |
2709 } else { | |
2710 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); | |
2711 } | |
2712 dst = setcc_r(dst, CC_C, FLAG_C); | |
2713 dst = jmp(dst, dst+4); | |
2714 *neq_32_off = dst - (neq_32_off+1); | |
2715 } | |
2716 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | |
2717 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); | |
2718 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | |
2657 if (dst_op->mode == MODE_REG_DIRECT) { | 2719 if (dst_op->mode == MODE_REG_DIRECT) { |
2658 dst = special(dst, 1, dst_op->base, SZ_D); | 2720 dst = xor_rr(dst, dst_op->base, dst_op->base, inst->extra.size); |
2659 } else { | 2721 } else { |
2660 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); | 2722 dst = mov_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); |
2661 } | 2723 } |
2662 dst = setcc_r(dst, CC_C, FLAG_C); | 2724 } else { |
2663 dst = jmp(dst, dst+4); | 2725 if (dst_op->mode == MODE_REG_DIRECT) { |
2664 *neq_32_off = dst - (neq_32_off+1); | 2726 dst = shift_ir(dst, 31, dst_op->base, inst->extra.size); |
2665 } | 2727 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2666 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 2728 } else { |
2667 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); | 2729 dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); |
2668 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | 2730 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2731 } | |
2732 | |
2733 } | |
2734 end_off = dst+1; | |
2735 dst = jmp(dst, dst+2); | |
2736 *norm_shift_off = dst - (norm_shift_off+1); | |
2669 if (dst_op->mode == MODE_REG_DIRECT) { | 2737 if (dst_op->mode == MODE_REG_DIRECT) { |
2670 dst = xor_rr(dst, dst_op->base, dst_op->base, inst->extra.size); | 2738 dst = shift_clr(dst, dst_op->base, inst->extra.size); |
2671 } else { | 2739 } else { |
2672 dst = mov_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | 2740 dst = shift_clrdisp8(dst, dst_op->base, dst_op->disp, inst->extra.size); |
2673 } | 2741 } |
2674 } else { | 2742 } |
2675 if (dst_op->mode == MODE_REG_DIRECT) { | |
2676 dst = shift_ir(dst, 31, dst_op->base, inst->extra.size); | |
2677 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | |
2678 } else { | |
2679 dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); | |
2680 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | |
2681 } | |
2682 | |
2683 } | |
2684 end_off = dst+1; | |
2685 dst = jmp(dst, dst+2); | |
2686 *norm_shift_off = dst - (norm_shift_off+1); | |
2687 if (dst_op->mode == MODE_REG_DIRECT) { | |
2688 dst = shift_clr(dst, dst_op->base, inst->extra.size); | |
2689 } else { | |
2690 dst = shift_clrdisp8(dst, dst_op->base, dst_op->disp, inst->extra.size); | |
2691 } | |
2692 | |
2693 } | 2743 } |
2694 | 2744 |
2695 } | 2745 } |
2696 if (!special && end_off) { | 2746 if (!special && end_off) { |
2697 *end_off = dst - (end_off + 1); | 2747 *end_off = dst - (end_off + 1); |
2700 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2750 dst = setcc_r(dst, CC_Z, FLAG_Z); |
2701 dst = setcc_r(dst, CC_S, FLAG_N); | 2751 dst = setcc_r(dst, CC_S, FLAG_N); |
2702 if (special && end_off) { | 2752 if (special && end_off) { |
2703 *end_off = dst - (end_off + 1); | 2753 *end_off = dst - (end_off + 1); |
2704 } | 2754 } |
2705 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | |
2706 //set X flag to same as C flag | 2755 //set X flag to same as C flag |
2707 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2756 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); |
2757 if (z_off) { | |
2758 *z_off = dst - (z_off + 1); | |
2759 } | |
2760 if (inst->op != M68K_ASL && inst->src.addr_mode != MODE_UNUSED && !(src_op->mode == MODE_IMMED && src_op->disp == 1)) { | |
2761 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | |
2762 } | |
2708 if (inst->src.addr_mode == MODE_UNUSED) { | 2763 if (inst->src.addr_mode == MODE_UNUSED) { |
2709 dst = m68k_save_result(inst, dst, opts); | 2764 dst = m68k_save_result(inst, dst, opts); |
2710 } | 2765 } |
2711 return dst; | 2766 return dst; |
2712 } | 2767 } |