comparison m68k_to_x86.c @ 71:f80fa1776507

Implement more instructions and address modes
author Mike Pavone <pavone@retrodev.com>
date Fri, 21 Dec 2012 01:00:52 -0800
parents cebd0b5ac7f0
children 8da611e69b32
comparison
equal deleted inserted replaced
70:cebd0b5ac7f0 71:f80fa1776507
92 //We only get one memory parameter, so if the dst operand is a register in memory, 92 //We only get one memory parameter, so if the dst operand is a register in memory,
93 //we need to copy this to a temp register first 93 //we need to copy this to a temp register first
94 reg = native_reg(&(inst->dst), opts); 94 reg = native_reg(&(inst->dst), opts);
95 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode == MODE_AREG) 95 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode == MODE_AREG)
96 || inst->op == M68K_EXG) { 96 || inst->op == M68K_EXG) {
97 97
98 ea->mode = MODE_REG_DISPLACE8; 98 ea->mode = MODE_REG_DISPLACE8;
99 ea->base = CONTEXT; 99 ea->base = CONTEXT;
100 ea->disp = reg_offset(&(inst->src)); 100 ea->disp = reg_offset(&(inst->src));
101 } else { 101 } else {
102 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, inst->extra.size); 102 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, inst->extra.size);
137 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 137 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
138 out = add_ir(out, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); 138 out = add_ir(out, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D);
139 } else { 139 } else {
140 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); 140 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D);
141 } 141 }
142 }
143 ea->mode = MODE_REG_DIRECT;
144 ea->base = SCRATCH1;
145 break;
146 case MODE_AREG_DISPLACE:
147 out = cycles(out, BUS);
148 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
149 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D);
150 } else {
151 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D);
152 }
153 out = add_ir(out, inst->src.params.regs.displacement, SCRATCH1, SZ_D);
154 switch (inst->extra.size)
155 {
156 case OPSIZE_BYTE:
157 out = call(out, (char *)m68k_read_byte_scratch1);
158 break;
159 case OPSIZE_WORD:
160 out = call(out, (char *)m68k_read_word_scratch1);
161 break;
162 case OPSIZE_LONG:
163 out = call(out, (char *)m68k_read_long_scratch1);
164 break;
165 }
166 ea->mode = MODE_REG_DIRECT;
167 ea->base = SCRATCH1;
168 break;
169 case MODE_PC_DISPLACE:
170 out = cycles(out, BUS);
171 out = mov_ir(out, inst->src.params.regs.displacement + inst->address, SCRATCH1, SZ_D);
172 switch (inst->extra.size)
173 {
174 case OPSIZE_BYTE:
175 out = call(out, (char *)m68k_read_byte_scratch1);
176 break;
177 case OPSIZE_WORD:
178 out = call(out, (char *)m68k_read_word_scratch1);
179 break;
180 case OPSIZE_LONG:
181 out = call(out, (char *)m68k_read_long_scratch1);
182 break;
142 } 183 }
143 ea->mode = MODE_REG_DIRECT; 184 ea->mode = MODE_REG_DIRECT;
144 ea->base = SCRATCH1; 185 ea->base = SCRATCH1;
145 break; 186 break;
146 case MODE_ABSOLUTE: 187 case MODE_ABSOLUTE:
229 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); 270 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D);
230 } else { 271 } else {
231 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); 272 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D);
232 } 273 }
233 274
234 if (inst->src.addr_mode == MODE_AREG_POSTINC) { 275 if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
235 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : 1); 276 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : 1);
236 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { 277 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
237 out = add_ir(out, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); 278 out = add_ir(out, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D);
238 } else { 279 } else {
239 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); 280 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
240 } 281 }
241 } 282 }
283 ea->mode = MODE_REG_DIRECT;
284 ea->base = SCRATCH1;
285 break;
286 case MODE_AREG_DISPLACE:
287 out = cycles(out, BUS);
288 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
289 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D);
290 } else {
291 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D);
292 }
293 out = add_ir(out, inst->dst.params.regs.displacement, SCRATCH1, SZ_D);
294 out = push_r(out, SCRATCH1);
295 switch (inst->extra.size)
296 {
297 case OPSIZE_BYTE:
298 out = call(out, (char *)m68k_read_byte_scratch1);
299 break;
300 case OPSIZE_WORD:
301 out = call(out, (char *)m68k_read_word_scratch1);
302 break;
303 case OPSIZE_LONG:
304 out = call(out, (char *)m68k_read_long_scratch1);
305 break;
306 }
307 out = pop_r(out, SCRATCH2);
308 ea->mode = MODE_REG_DIRECT;
309 ea->base = SCRATCH1;
310 break;
311 case MODE_PC_DISPLACE:
312 out = cycles(out, BUS);
313 out = mov_ir(out, inst->dst.params.regs.displacement + inst->address, SCRATCH1, SZ_D);
314 out = push_r(out, SCRATCH1);
315 switch (inst->extra.size)
316 {
317 case OPSIZE_BYTE:
318 out = call(out, (char *)m68k_read_byte_scratch1);
319 break;
320 case OPSIZE_WORD:
321 out = call(out, (char *)m68k_read_word_scratch1);
322 break;
323 case OPSIZE_LONG:
324 out = call(out, (char *)m68k_read_long_scratch1);
325 break;
326 }
327 out = pop_r(out, SCRATCH2);
242 ea->mode = MODE_REG_DIRECT; 328 ea->mode = MODE_REG_DIRECT;
243 ea->base = SCRATCH1; 329 ea->base = SCRATCH1;
244 break; 330 break;
245 case MODE_ABSOLUTE: 331 case MODE_ABSOLUTE:
246 case MODE_ABSOLUTE_SHORT: 332 case MODE_ABSOLUTE_SHORT:
452 } else { 538 } else {
453 dst = add_irdisp8(dst, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); 539 dst = add_irdisp8(dst, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
454 } 540 }
455 } 541 }
456 break; 542 break;
543 case MODE_AREG_DISPLACE:
544 dst = cycles(dst, BUS);
545 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
546 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D);
547 } else {
548 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D);
549 }
550 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D);
551 if (src.mode == MODE_REG_DIRECT) {
552 if (src.base != SCRATCH1) {
553 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size);
554 }
555 } else if (src.mode == MODE_REG_DISPLACE8) {
556 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size);
557 } else {
558 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size);
559 }
560 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size);
561 dst = setcc_r(dst, CC_Z, FLAG_Z);
562 dst = setcc_r(dst, CC_S, FLAG_N);
563 switch (inst->extra.size)
564 {
565 case OPSIZE_BYTE:
566 dst = call(dst, (char *)m68k_write_byte);
567 break;
568 case OPSIZE_WORD:
569 dst = call(dst, (char *)m68k_write_word);
570 break;
571 case OPSIZE_LONG:
572 dst = call(dst, (char *)m68k_write_long_highfirst);
573 break;
574 }
575 break;
576 case MODE_PC_DISPLACE:
577 dst = cycles(dst, BUS);
578 dst = mov_ir(dst, inst->dst.params.regs.displacement + inst->address, SCRATCH2, SZ_D);
579 if (src.mode == MODE_REG_DIRECT) {
580 if (src.base != SCRATCH1) {
581 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size);
582 }
583 } else if (src.mode == MODE_REG_DISPLACE8) {
584 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size);
585 } else {
586 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size);
587 }
588 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size);
589 dst = setcc_r(dst, CC_Z, FLAG_Z);
590 dst = setcc_r(dst, CC_S, FLAG_N);
591 switch (inst->extra.size)
592 {
593 case OPSIZE_BYTE:
594 dst = call(dst, (char *)m68k_write_byte);
595 break;
596 case OPSIZE_WORD:
597 dst = call(dst, (char *)m68k_write_word);
598 break;
599 case OPSIZE_LONG:
600 dst = call(dst, (char *)m68k_write_long_highfirst);
601 break;
602 }
603 break;
457 case MODE_ABSOLUTE: 604 case MODE_ABSOLUTE:
458 case MODE_ABSOLUTE_SHORT: 605 case MODE_ABSOLUTE_SHORT:
459 if (src.mode == MODE_REG_DIRECT) { 606 if (src.mode == MODE_REG_DIRECT) {
460 if (src.base != SCRATCH1) { 607 if (src.base != SCRATCH1) {
461 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); 608 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size);
492 exit(1); 639 exit(1);
493 } 640 }
494 641
495 //add cycles for prefetch 642 //add cycles for prefetch
496 dst = cycles(dst, BUS); 643 dst = cycles(dst, BUS);
644 return dst;
645 }
646
647 uint8_t * translate_m68k_movem(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
648 {
649 int8_t bit,reg;
650 uint8_t early_cycles;
651 if(inst->src.addr_mode == MODE_REG) {
652 //reg to mem
653 early_cycles = 8;
654 int8_t dir;
655 if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
656 reg = 15;
657 dir = -1;
658 } else {
659 reg = 0;
660 }
661 switch (inst->dst.addr_mode)
662 {
663 case MODE_AREG_INDIRECT:
664 case MODE_AREG_PREDEC:
665 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
666 dst = mov_rr(dst, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D);
667 } else {
668 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D);
669 }
670 break;
671 case MODE_ABSOLUTE:
672 early_cycles += 4;
673 case MODE_ABSOLUTE_SHORT:
674 early_cycles += 4;
675 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D);
676 break;
677 default:
678 printf("address mode %d not implemented (movem dst)\n", inst->dst.addr_mode);
679 exit(1);
680 }
681 dst = cycles(dst, early_cycles);
682 for(bit=0; reg < 16 && reg >= 0; reg += dir, bit++) {
683 if (inst->src.params.immed & (1 << bit)) {
684 if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
685 dst = sub_ir(dst, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, SCRATCH2, SZ_D);
686 }
687 dst = push_r(dst, SCRATCH2);
688 if (reg > 7) {
689 if (opts->aregs[reg-8] >= 0) {
690 dst = mov_rr(dst, opts->aregs[reg-8], SCRATCH1, inst->extra.size);
691 } else {
692 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), SCRATCH1, inst->extra.size);
693 }
694 } else {
695 if (opts->dregs[reg] >= 0) {
696 dst = mov_rr(dst, opts->dregs[reg], SCRATCH1, inst->extra.size);
697 } else {
698 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), SCRATCH1, inst->extra.size);
699 }
700 }
701 if (inst->extra.size == OPSIZE_LONG) {
702 dst = call(dst, (uint8_t *)m68k_write_long_lowfirst);
703 } else {
704 dst = call(dst, (uint8_t *)m68k_write_word);
705 }
706 dst = pop_r(dst, SCRATCH2);
707 if (inst->dst.addr_mode != MODE_AREG_PREDEC) {
708 dst = add_ir(dst, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, SCRATCH2, SZ_D);
709 }
710 }
711 }
712 if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
713 if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
714 dst = mov_rr(dst, SCRATCH2, opts->aregs[inst->dst.params.regs.pri], SZ_D);
715 } else {
716 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
717 }
718 }
719 } else {
720 //mem to reg
721 early_cycles = 4;
722 switch (inst->src.addr_mode)
723 {
724 case MODE_AREG_INDIRECT:
725 case MODE_AREG_POSTINC:
726 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
727 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D);
728 } else {
729 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D);
730 }
731 break;
732 case MODE_ABSOLUTE:
733 early_cycles += 4;
734 case MODE_ABSOLUTE_SHORT:
735 early_cycles += 4;
736 dst = mov_ir(dst, inst->src.params.immed, SCRATCH1, SZ_D);
737 break;
738 default:
739 printf("address mode %d not implemented (movem src)\n", inst->src.addr_mode);
740 exit(1);
741 }
742 dst = cycles(dst, early_cycles);
743 for(reg = 0; reg < 16; reg ++) {
744 if (inst->src.params.immed & (1 << reg)) {
745 dst = push_r(dst, SCRATCH1);
746 if (inst->extra.size == OPSIZE_LONG) {
747 dst = call(dst, (uint8_t *)m68k_read_long_scratch1);
748 } else {
749 dst = call(dst, (uint8_t *)m68k_read_word_scratch1);
750 }
751 if (reg > 7) {
752 if (opts->aregs[reg-8] >= 0) {
753 dst = mov_rr(dst, SCRATCH1, opts->aregs[reg-8], inst->extra.size);
754 } else {
755 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), inst->extra.size);
756 }
757 } else {
758 if (opts->dregs[reg] >= 0) {
759 dst = mov_rr(dst, SCRATCH1, opts->dregs[reg], inst->extra.size);
760 } else {
761 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), inst->extra.size);
762 }
763 }
764 dst = pop_r(dst, SCRATCH1);
765 dst = add_ir(dst, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, SCRATCH1, SZ_D);
766 }
767 }
768 if (inst->src.addr_mode == MODE_AREG_POSTINC) {
769 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
770 dst = mov_rr(dst, SCRATCH2, opts->aregs[inst->src.params.regs.pri], SZ_D);
771 } else {
772 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, reg_offset(&(inst->src)), SZ_D);
773 }
774 }
775 }
776 //prefetch
777 dst = cycles(dst, 4);
497 return dst; 778 return dst;
498 } 779 }
499 780
500 uint8_t * translate_m68k_clr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 781 uint8_t * translate_m68k_clr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
501 { 782 {
553 } else { 834 } else {
554 dst = add_irdisp8(dst, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); 835 dst = add_irdisp8(dst, inc_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
555 } 836 }
556 } 837 }
557 break; 838 break;
839 default:
840 printf("address mode %d not implemented (clr dst)\n", inst->dst.addr_mode);
841 exit(1);
558 } 842 }
559 return dst; 843 return dst;
560 } 844 }
561 845
562 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 846 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
563 { 847 {
564 int8_t dst_reg = native_reg(&(inst->dst), opts); 848 int8_t dst_reg = native_reg(&(inst->dst), opts);
565 switch(inst->src.addr_mode) 849 switch(inst->src.addr_mode)
566 { 850 {
567 case MODE_AREG_INDIRECT: 851 case MODE_AREG_INDIRECT:
568 dst = cycles(dst, BUS); 852 dst = cycles(dst, BUS);
569 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 853 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
570 if (dst_reg >= 0) { 854 if (dst_reg >= 0) {
571 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); 855 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D);
572 } else { 856 } else {
573 dst = mov_rrdisp8(dst, opts->aregs[inst->src.params.regs.pri], CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); 857 dst = mov_rrdisp8(dst, opts->aregs[inst->src.params.regs.pri], CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D);
574 } 858 }
575 } else { 859 } else {
576 if (dst_reg >= 0) { 860 if (dst_reg >= 0) {
577 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, dst_reg, SZ_D); 861 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, dst_reg, SZ_D);
578 } else { 862 } else {
579 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); 863 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D);
580 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); 864 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D);
581 } 865 }
582 } 866 }
583 break; 867 break;
584 case MODE_ABSOLUTE: 868 case MODE_AREG_DISPLACE:
585 case MODE_ABSOLUTE_SHORT: 869 dst = cycles(dst, 8);
586 dst = cycles(dst, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); 870 if (dst_reg >= 0) {
587 if (dst_reg >= 0) { 871 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
588 dst = mov_ir(dst, inst->src.params.immed, dst_reg, SZ_D); 872 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D);
589 } else { 873 } else {
590 dst = mov_irdisp8(dst, inst->src.params.immed, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); 874 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), dst_reg, SZ_D);
591 } 875 }
592 break; 876 dst = add_ir(dst, inst->src.params.regs.displacement, dst_reg, SZ_D);
593 } 877 } else {
878 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
879 dst = mov_rrdisp8(dst, opts->aregs[inst->src.params.regs.pri], CONTEXT, reg_offset(&(inst->dst)), SZ_D);
880 } else {
881 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D);
882 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst)), SZ_D);
883 }
884 dst = add_irdisp8(dst, inst->src.params.regs.displacement, CONTEXT, reg_offset(&(inst->src)), SZ_D);
885 }
886 break;
887 case MODE_PC_DISPLACE:
888 dst = cycles(dst, 8);
889 if (dst_reg >= 0) {
890 dst = mov_ir(dst, inst->src.params.regs.displacement + inst->address, dst_reg, SZ_D);
891 } else {
892 dst = mov_irdisp8(dst, inst->src.params.regs.displacement + inst->address, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D);
893 }
894 break;
895 case MODE_ABSOLUTE:
896 case MODE_ABSOLUTE_SHORT:
897 dst = cycles(dst, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2);
898 if (dst_reg >= 0) {
899 dst = mov_ir(dst, inst->src.params.immed, dst_reg, SZ_D);
900 } else {
901 dst = mov_irdisp8(dst, inst->src.params.immed, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D);
902 }
903 break;
904 default:
905 printf("address mode %d not implemented (lea src)\n", inst->src.addr_mode);
906 exit(1);
907 }
594 return dst; 908 return dst;
595 } 909 }
596 910
597 uint8_t * translate_m68k_bsr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 911 uint8_t * translate_m68k_bsr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
598 { 912 {
685 } 999 }
686 1000
687 uint8_t * translate_m68k_jmp(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 1001 uint8_t * translate_m68k_jmp(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
688 { 1002 {
689 uint8_t * dest_addr; 1003 uint8_t * dest_addr;
690 switch(inst->src.addr_mode) 1004 switch(inst->src.addr_mode)
691 { 1005 {
692 case MODE_AREG_INDIRECT: 1006 case MODE_AREG_INDIRECT:
693 dst = cycles(dst, BUS); 1007 dst = cycles(dst, BUS);
694 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 1008 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
695 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); 1009 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D);
696 } else { 1010 } else {
697 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); 1011 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D);
698 } 1012 }
699 dst = call(dst, (uint8_t *)m68k_native_addr); 1013 dst = call(dst, (uint8_t *)m68k_native_addr);
700 //TODO: Finish me 1014 //TODO: Finish me
701 //TODO: Fix timing 1015 //TODO: Fix timing
702 break; 1016 break;
703 case MODE_ABSOLUTE: 1017 case MODE_ABSOLUTE:
704 case MODE_ABSOLUTE_SHORT: 1018 case MODE_ABSOLUTE_SHORT:
705 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); 1019 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10);
706 dest_addr = get_native_address(opts->native_code_map, inst->src.params.immed); 1020 dest_addr = get_native_address(opts->native_code_map, inst->src.params.immed);
707 if (!dest_addr) { 1021 if (!dest_addr) {
708 opts->deferred = defer_address(opts->deferred, inst->src.params.immed, dst + 1); 1022 opts->deferred = defer_address(opts->deferred, inst->src.params.immed, dst + 1);
709 //dummy address to be replaced later, make sure it generates a 4-byte displacement 1023 //dummy address to be replaced later, make sure it generates a 4-byte displacement
710 dest_addr = dst + 256; 1024 dest_addr = dst + 256;
711 } 1025 }
712 dst = jmp(dst, dest_addr); 1026 dst = jmp(dst, dest_addr);
713 break; 1027 break;
714 } 1028 }
715 return dst; 1029 return dst;
716 } 1030 }
717 1031
718 uint8_t * translate_m68k_rts(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 1032 uint8_t * translate_m68k_rts(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
719 { 1033 {
927 return translate_m68k_rts(dst, inst, opts); 1241 return translate_m68k_rts(dst, inst, opts);
928 } else if(inst->op == M68K_DBCC) { 1242 } else if(inst->op == M68K_DBCC) {
929 return translate_m68k_dbcc(dst, inst, opts); 1243 return translate_m68k_dbcc(dst, inst, opts);
930 } else if(inst->op == M68K_CLR) { 1244 } else if(inst->op == M68K_CLR) {
931 return translate_m68k_clr(dst, inst, opts); 1245 return translate_m68k_clr(dst, inst, opts);
1246 } else if(inst->op == M68K_MOVEM) {
1247 return translate_m68k_movem(dst, inst, opts);
932 } 1248 }
933 x86_ea src_op, dst_op; 1249 x86_ea src_op, dst_op;
934 if (inst->src.addr_mode != MODE_UNUSED) { 1250 if (inst->src.addr_mode != MODE_UNUSED) {
935 dst = translate_m68k_src(inst, &src_op, dst, opts); 1251 dst = translate_m68k_src(inst, &src_op, dst, opts);
936 } 1252 }
1096 dst = m68k_save_result(inst, dst, opts); 1412 dst = m68k_save_result(inst, dst, opts);
1097 break; 1413 break;
1098 /*case M68K_EORI_CCR: 1414 /*case M68K_EORI_CCR:
1099 case M68K_EORI_SR:*/ 1415 case M68K_EORI_SR:*/
1100 case M68K_EXG: 1416 case M68K_EXG:
1101 dst = cycles(dst, 6); 1417 dst = cycles(dst, 6);
1102 if (dst_op.mode == MODE_REG_DIRECT) { 1418 if (dst_op.mode == MODE_REG_DIRECT) {
1103 dst = mov_rr(dst, dst_op.base, SCRATCH2, SZ_D); 1419 dst = mov_rr(dst, dst_op.base, SCRATCH2, SZ_D);
1104 if (src_op.mode == MODE_REG_DIRECT) { 1420 if (src_op.mode == MODE_REG_DIRECT) {
1105 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_D); 1421 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_D);
1106 dst = mov_rr(dst, SCRATCH2, src_op.base, SZ_D); 1422 dst = mov_rr(dst, SCRATCH2, src_op.base, SZ_D);
1107 } else { 1423 } else {
1108 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, SZ_D); 1424 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, SZ_D);
1109 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D); 1425 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D);
1110 } 1426 }
1111 } else { 1427 } else {
1112 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_D); 1428 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH2, SZ_D);
1113 if (src_op.mode == MODE_REG_DIRECT) { 1429 if (src_op.mode == MODE_REG_DIRECT) {
1114 dst = mov_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D); 1430 dst = mov_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D);
1115 dst = mov_rr(dst, SCRATCH2, src_op.base, SZ_D); 1431 dst = mov_rr(dst, SCRATCH2, src_op.base, SZ_D);
1116 } else { 1432 } else {
1117 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D); 1433 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_D);
1118 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D); 1434 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D);
1119 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D); 1435 dst = mov_rrdisp8(dst, SCRATCH2, src_op.base, src_op.disp, SZ_D);
1120 } 1436 }
1121 } 1437 }
1122 break; 1438 break;
1123 case M68K_EXT: 1439 case M68K_EXT:
1124 break; 1440 break;
1125 case M68K_ILLEGAL: 1441 case M68K_ILLEGAL:
1126 dst = call(dst, (uint8_t *)m68k_save_context); 1442 dst = call(dst, (uint8_t *)m68k_save_context);
1127 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); 1443 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
1128 dst = call(dst, (uint8_t *)print_regs_exit); 1444 dst = call(dst, (uint8_t *)print_regs_exit);
1129 break; 1445 break;
1130 /*case M68K_JSR: 1446 /*case M68K_JSR:
1131 case M68K_LEA: 1447 case M68K_LEA:
1132 case M68K_LINK: 1448 case M68K_LINK:
1449 case M68K_MOVE_FROM_SR:
1450 break;*/
1133 case M68K_MOVE_CCR: 1451 case M68K_MOVE_CCR:
1134 case M68K_MOVE_FROM_SR:
1135 case M68K_MOVE_SR: 1452 case M68K_MOVE_SR:
1136 case M68K_MOVE_USP: 1453 //TODO: Privilege check for MOVE to SR
1137 case M68K_MOVEM: 1454 if (src_op.mode == MODE_IMMED) {
1455 dst = mov_ir(dst, src_op.disp & 0x1, FLAG_C, SZ_B);
1456 dst = mov_ir(dst, (src_op.disp >> 1) & 0x1, FLAG_V, SZ_B);
1457 dst = mov_ir(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, SZ_B);
1458 dst = mov_ir(dst, (src_op.disp >> 3) & 0x1, FLAG_N, SZ_B);
1459 dst = mov_irind(dst, (src_op.disp >> 4) & 0x1, CONTEXT, SZ_B);
1460 if (inst->op == M68K_MOVE_SR) {
1461 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B);
1462 }
1463 dst = cycles(dst, 12);
1464 } else {
1465 if (src_op.mode == MODE_REG_DIRECT) {
1466 dst = mov_rr(dst, src_op.base, FLAG_C, SZ_B);
1467 } else {
1468 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, FLAG_C, SZ_B);
1469 }
1470 dst = mov_rr(dst, FLAG_C, FLAG_V, SZ_B);
1471 dst = and_ir(dst, 1, FLAG_C, SZ_B);
1472 dst = shr_ir(dst, 1, FLAG_V, SZ_B);
1473 dst = mov_rr(dst, FLAG_V, FLAG_Z, SZ_B);
1474 dst = and_ir(dst, 1, FLAG_V, SZ_B);
1475 dst = shr_ir(dst, 1, FLAG_Z, SZ_B);
1476 dst = mov_rr(dst, FLAG_Z, FLAG_N, SZ_B);
1477 dst = and_ir(dst, 1, FLAG_Z, SZ_B);
1478 dst = shr_ir(dst, 1, FLAG_N, SZ_B);
1479 dst = mov_rr(dst, 1, SCRATCH2, SZ_B);
1480 dst = shr_ir(dst, 1, SCRATCH2, SZ_B);
1481 dst = and_ir(dst, 1, SCRATCH2, SZ_B);
1482 dst = mov_rrind(dst, SCRATCH2, CONTEXT, SZ_B);
1483 dst = cycles(dst, 12);
1484 if (inst->op == M68K_MOVE_SR) {
1485 if (src_op.mode == MODE_REG_DIRECT) {
1486 dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_W);
1487 } else {
1488 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W);
1489 }
1490 }
1491 dst = shr_ir(dst, 8, SCRATCH2, SZ_B);
1492 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, offsetof(m68k_context, status), SZ_B);
1493 }
1494 break;
1495 /*case M68K_MOVE_USP:
1138 case M68K_MOVEP: 1496 case M68K_MOVEP:
1139 case M68K_MULS: 1497 case M68K_MULS:
1140 case M68K_MULU: 1498 case M68K_MULU:
1141 case M68K_NBCD: 1499 case M68K_NBCD:
1142 case M68K_NEG: 1500 case M68K_NEG:
1283 m68k_start_context(addr, context); 1641 m68k_start_context(addr, context);
1284 } 1642 }
1285 1643
1286 void m68k_reset(m68k_context * context) 1644 void m68k_reset(m68k_context * context)
1287 { 1645 {
1288 //TODO: Make this actually use the normal read functions 1646 //TODO: Make this actually use the normal read functions
1289 context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1]; 1647 context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1];
1290 uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3]; 1648 uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3];
1291 start_68k_context(context, address); 1649 start_68k_context(context, address);
1292 } 1650 }
1293 1651
1294 void init_x86_68k_opts(x86_68k_options * opts) 1652 void init_x86_68k_opts(x86_68k_options * opts)
1295 { 1653 {
1296 opts->flags = 0; 1654 opts->flags = 0;