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: