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 }