Mercurial > repos > blastem
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; |