Mercurial > repos > blastem
comparison m68k_to_x86.c @ 51:937b47c9b79b
Implement shift instructions (asl, lsl, asr, lsr). Add flags to register printout. Fix minor bug in shift/rotate instruction decoding.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 15 Dec 2012 23:01:32 -0800 |
parents | d2e43d64e999 |
children | f02ba3808757 |
comparison
equal
deleted
inserted
replaced
50:4836d1f3841a | 51:937b47c9b79b |
---|---|
61 return -1; | 61 return -1; |
62 } | 62 } |
63 | 63 |
64 void print_regs_exit(m68k_context * context) | 64 void print_regs_exit(m68k_context * context) |
65 { | 65 { |
66 printf("XNVZC\n%d%d%d%d%d\n", context->flags[0], context->flags[1], context->flags[2], context->flags[3], context->flags[4]); | |
66 for (int i = 0; i < 8; i++) { | 67 for (int i = 0; i < 8; i++) { |
67 printf("d%d: %X\n", i, context->dregs[i]); | 68 printf("d%d: %X\n", i, context->dregs[i]); |
68 } | 69 } |
69 for (int i = 0; i < 8; i++) { | 70 for (int i = 0; i < 8; i++) { |
70 printf("a%d: %X\n", i, context->aregs[i]); | 71 printf("a%d: %X\n", i, context->aregs[i]); |
637 dst = cycles(dst, 4); | 638 dst = cycles(dst, 4); |
638 } | 639 } |
639 dst = check_cycles(dst); | 640 dst = check_cycles(dst); |
640 } | 641 } |
641 | 642 |
643 typedef uint8_t * (*shift_ir_t)(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size); | |
644 typedef uint8_t * (*shift_irdisp8_t)(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t disp, uint8_t size); | |
645 typedef uint8_t * (*shift_clr_t)(uint8_t * out, uint8_t dst, uint8_t size); | |
646 typedef uint8_t * (*shift_clrdisp8_t)(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size); | |
647 | |
648 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) | |
649 { | |
650 uint8_t * end_off = NULL; | |
651 if (inst->src.addr_mode == MODE_UNUSED) { | |
652 dst = cycles(dst, BUS); | |
653 dst = check_cycles(dst); | |
654 //Memory shift | |
655 dst = shift_ir(dst, 1, dst_op->base, SZ_W); | |
656 } else { | |
657 dst = cycles(dst, inst->extra.size == OPSIZE_LONG ? 8 : 6); | |
658 dst = check_cycles(dst); | |
659 if (src_op->mode == MODE_IMMED) { | |
660 if (dst_op->mode == MODE_REG_DIRECT) { | |
661 dst = shift_ir(dst, src_op->disp, dst_op->base, inst->extra.size); | |
662 } else { | |
663 dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | |
664 } | |
665 } else { | |
666 if (src_op->base != RCX) { | |
667 if (src_op->mode == MODE_REG_DIRECT) { | |
668 dst = mov_rr(dst, src_op->base, RCX, SZ_B); | |
669 } else { | |
670 dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); | |
671 } | |
672 } | |
673 dst = and_ir(dst, 63, RCX, SZ_D); | |
674 //add 2 cycles for every bit shifted | |
675 dst = add_rr(dst, RCX, CYCLES, SZ_D); | |
676 dst = add_rr(dst, RCX, CYCLES, SZ_D); | |
677 //x86 shifts modulo 32 for operand sizes less than 64-bits | |
678 //but M68K shifts modulo 64, so we need to check for large shifts here | |
679 dst = cmp_ir(dst, 32, RCX, SZ_B); | |
680 uint8_t * norm_shift_off = dst + 1; | |
681 dst = jcc(dst, CC_L, dst+2); | |
682 if (special) { | |
683 if (inst->extra.size == OPSIZE_LONG) { | |
684 uint8_t * neq_32_off = dst + 1; | |
685 dst = jcc(dst, CC_NZ, dst+2); | |
686 | |
687 //set the carry bit to the lsb | |
688 if (dst_op->mode == MODE_REG_DIRECT) { | |
689 dst = special(dst, 1, dst_op->base, SZ_D); | |
690 } else { | |
691 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); | |
692 } | |
693 dst = setcc_r(dst, CC_C, FLAG_C); | |
694 dst = jmp(dst, dst+4); | |
695 *neq_32_off = dst - (neq_32_off+1); | |
696 } | |
697 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | |
698 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); | |
699 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | |
700 if (dst_op->mode == MODE_REG_DIRECT) { | |
701 dst = xor_rr(dst, dst_op->base, dst_op->base, inst->extra.size); | |
702 } else { | |
703 dst = mov_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | |
704 } | |
705 } else { | |
706 if (dst_op->mode == MODE_REG_DIRECT) { | |
707 dst = shift_ir(dst, 31, dst_op->base, inst->extra.size); | |
708 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | |
709 } else { | |
710 dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); | |
711 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | |
712 } | |
713 | |
714 } | |
715 end_off = dst+1; | |
716 dst = jmp(dst, dst+2); | |
717 *norm_shift_off = dst - (norm_shift_off+1); | |
718 if (dst_op->mode == MODE_REG_DIRECT) { | |
719 dst = shift_clr(dst, dst_op->base, inst->extra.size); | |
720 } else { | |
721 dst = shift_clrdisp8(dst, dst_op->base, dst_op->disp, inst->extra.size); | |
722 } | |
723 | |
724 } | |
725 | |
726 } | |
727 if (!special && end_off) { | |
728 *end_off = dst - (end_off + 1); | |
729 } | |
730 dst = setcc_r(dst, CC_C, FLAG_C); | |
731 dst = setcc_r(dst, CC_Z, FLAG_Z); | |
732 dst = setcc_r(dst, CC_S, FLAG_N); | |
733 if (special && end_off) { | |
734 *end_off = dst - (end_off + 1); | |
735 } | |
736 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | |
737 //set X flag to same as C flag | |
738 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | |
739 if (inst->src.addr_mode == MODE_UNUSED) { | |
740 dst = m68k_save_result(inst, dst, opts); | |
741 } else { | |
742 dst = check_cycles(dst); | |
743 } | |
744 } | |
745 | |
642 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 746 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) |
643 { | 747 { |
748 uint8_t * end_off; | |
644 map_native_address(opts->native_code_map, inst->address, dst); | 749 map_native_address(opts->native_code_map, inst->address, dst); |
645 if (inst->op == M68K_MOVE) { | 750 if (inst->op == M68K_MOVE) { |
646 return translate_m68k_move(dst, inst, opts); | 751 return translate_m68k_move(dst, inst, opts); |
647 } else if(inst->op == M68K_LEA) { | 752 } else if(inst->op == M68K_LEA) { |
648 return translate_m68k_lea(dst, inst, opts); | 753 return translate_m68k_lea(dst, inst, opts); |
717 dst = check_cycles(dst); | 822 dst = check_cycles(dst); |
718 dst = m68k_save_result(inst, dst, opts); | 823 dst = m68k_save_result(inst, dst, opts); |
719 break; | 824 break; |
720 case M68K_ANDI_CCR: | 825 case M68K_ANDI_CCR: |
721 case M68K_ANDI_SR: | 826 case M68K_ANDI_SR: |
827 break; | |
722 case M68K_ASL: | 828 case M68K_ASL: |
723 case M68K_LSL: | 829 case M68K_LSL: |
830 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shl_ir, shl_irdisp8, shl_clr, shl_clrdisp8, shr_ir, shr_irdisp8); | |
831 break; | |
724 case M68K_ASR: | 832 case M68K_ASR: |
833 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, sar_ir, sar_irdisp8, sar_clr, sar_clrdisp8, NULL, NULL); | |
834 break; | |
725 case M68K_LSR: | 835 case M68K_LSR: |
836 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shr_ir, shr_irdisp8, shr_clr, shr_clrdisp8, shl_ir, shl_irdisp8); | |
837 break; | |
726 case M68K_BCHG: | 838 case M68K_BCHG: |
727 case M68K_BCLR: | 839 case M68K_BCLR: |
728 case M68K_BSET: | 840 case M68K_BSET: |
729 case M68K_BTST: | 841 case M68K_BTST: |
730 case M68K_CHK: | 842 case M68K_CHK: |