Mercurial > repos > blastem
comparison m68k_to_x86.c @ 184:ebcbdd1c4cc8
Fix a bunch of bugs in the CPU core, add a 68K debugger
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 13 Jan 2013 13:01:13 -0800 |
parents | 2f08d9e90a4c |
children | 8e138da572ab |
comparison
equal
deleted
inserted
replaced
183:2f08d9e90a4c | 184:ebcbdd1c4cc8 |
---|---|
36 void m68k_write_word(); | 36 void m68k_write_word(); |
37 void m68k_write_long_lowfirst(); | 37 void m68k_write_long_lowfirst(); |
38 void m68k_write_long_highfirst(); | 38 void m68k_write_long_highfirst(); |
39 void m68k_write_byte(); | 39 void m68k_write_byte(); |
40 void m68k_save_context(); | 40 void m68k_save_context(); |
41 void m68k_load_context(); | |
41 void m68k_modified_ret_addr(); | 42 void m68k_modified_ret_addr(); |
42 void m68k_native_addr(); | 43 void m68k_native_addr(); |
43 void m68k_native_addr_and_sync(); | 44 void m68k_native_addr_and_sync(); |
44 void m68k_trap(); | 45 void m68k_trap(); |
45 void m68k_invalid(); | 46 void m68k_invalid(); |
173 } else { | 174 } else { |
174 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); | 175 out = add_irdisp8(out, inc_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); |
175 } | 176 } |
176 } | 177 } |
177 ea->mode = MODE_REG_DIRECT; | 178 ea->mode = MODE_REG_DIRECT; |
178 ea->base = SCRATCH1; | 179 ea->base = (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? SCRATCH2 : SCRATCH1; |
179 break; | 180 break; |
180 case MODE_AREG_DISPLACE: | 181 case MODE_AREG_DISPLACE: |
181 out = cycles(out, BUS); | 182 out = cycles(out, BUS); |
182 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 183 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
183 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 184 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); |
390 ea->mode = MODE_REG_DISPLACE8; | 391 ea->mode = MODE_REG_DISPLACE8; |
391 ea->base = CONTEXT; | 392 ea->base = CONTEXT; |
392 ea->disp = reg_offset(&(inst->dst)); | 393 ea->disp = reg_offset(&(inst->dst)); |
393 break; | 394 break; |
394 case MODE_AREG_PREDEC: | 395 case MODE_AREG_PREDEC: |
396 if (inst->src.addr_mode == MODE_AREG_PREDEC) { | |
397 out = push_r(out, SCRATCH1); | |
398 } | |
395 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 399 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
396 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 400 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
397 out = sub_ir(out, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 401 out = sub_ir(out, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
398 } else { | 402 } else { |
399 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); | 403 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->dst)), SZ_D); |
419 case OPSIZE_LONG: | 423 case OPSIZE_LONG: |
420 out = call(out, (char *)m68k_read_long_scratch1); | 424 out = call(out, (char *)m68k_read_long_scratch1); |
421 break; | 425 break; |
422 } | 426 } |
423 } | 427 } |
424 //save reg value in SCRATCH2 so we can use it to save the result in memory later | 428 if (inst->src.addr_mode == MODE_AREG_PREDEC) { |
425 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 429 //restore src operand to SCRATCH2 |
426 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 430 out =pop_r(out, SCRATCH2); |
427 } else { | 431 } else { |
428 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 432 //save reg value in SCRATCH2 so we can use it to save the result in memory later |
433 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | |
434 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | |
435 } else { | |
436 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | |
437 } | |
429 } | 438 } |
430 | 439 |
431 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 440 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
432 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : 1); | 441 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : 1); |
433 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 442 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
642 } | 651 } |
643 | 652 |
644 uint8_t * m68k_save_result(m68kinst * inst, uint8_t * out, x86_68k_options * opts) | 653 uint8_t * m68k_save_result(m68kinst * inst, uint8_t * out, x86_68k_options * opts) |
645 { | 654 { |
646 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { | 655 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { |
656 if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) { | |
657 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | |
658 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | |
659 } else { | |
660 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | |
661 } | |
662 } | |
647 switch (inst->extra.size) | 663 switch (inst->extra.size) |
648 { | 664 { |
649 case OPSIZE_BYTE: | 665 case OPSIZE_BYTE: |
650 out = call(out, (char *)m68k_write_byte); | 666 out = call(out, (char *)m68k_write_byte); |
651 break; | 667 break; |
735 int32_t offset; | 751 int32_t offset; |
736 int32_t inc_amount, dec_amount; | 752 int32_t inc_amount, dec_amount; |
737 x86_ea src; | 753 x86_ea src; |
738 dst = translate_m68k_src(inst, &src, dst, opts); | 754 dst = translate_m68k_src(inst, &src, dst, opts); |
739 reg = native_reg(&(inst->dst), opts); | 755 reg = native_reg(&(inst->dst), opts); |
740 //update statically set flags | 756 if (inst->dst.addr_mode != MODE_AREG) { |
741 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 757 //update statically set flags |
742 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 758 dst = mov_ir(dst, 0, FLAG_V, SZ_B); |
759 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | |
760 } | |
743 | 761 |
744 if (src.mode == MODE_REG_DIRECT) { | 762 if (src.mode == MODE_REG_DIRECT) { |
745 flags_reg = src.base; | 763 flags_reg = src.base; |
746 } else { | 764 } else { |
747 if (reg >= 0) { | 765 if (reg >= 0) { |
773 } else if(src.mode == MODE_REG_DIRECT) { | 791 } else if(src.mode == MODE_REG_DIRECT) { |
774 dst = mov_rrdisp8(dst, src.base, CONTEXT, reg_offset(&(inst->dst)), size); | 792 dst = mov_rrdisp8(dst, src.base, CONTEXT, reg_offset(&(inst->dst)), size); |
775 } else { | 793 } else { |
776 dst = mov_irdisp8(dst, src.disp, CONTEXT, reg_offset(&(inst->dst)), size); | 794 dst = mov_irdisp8(dst, src.disp, CONTEXT, reg_offset(&(inst->dst)), size); |
777 } | 795 } |
778 dst = cmp_ir(dst, 0, flags_reg, size); | 796 if (inst->dst.addr_mode != MODE_AREG) { |
779 dst = setcc_r(dst, CC_Z, FLAG_Z); | 797 dst = cmp_ir(dst, 0, flags_reg, size); |
780 dst = setcc_r(dst, CC_S, FLAG_N); | 798 dst = setcc_r(dst, CC_Z, FLAG_Z); |
799 dst = setcc_r(dst, CC_S, FLAG_N); | |
800 } | |
781 break; | 801 break; |
782 case MODE_AREG_PREDEC: | 802 case MODE_AREG_PREDEC: |
783 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 803 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
784 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 804 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
785 dst = sub_ir(dst, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 805 dst = sub_ir(dst, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
800 } else if (src.mode == MODE_REG_DISPLACE8) { | 820 } else if (src.mode == MODE_REG_DISPLACE8) { |
801 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 821 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); |
802 } else { | 822 } else { |
803 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 823 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
804 } | 824 } |
805 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 825 if (inst->dst.addr_mode != MODE_AREG) { |
806 dst = setcc_r(dst, CC_Z, FLAG_Z); | 826 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
807 dst = setcc_r(dst, CC_S, FLAG_N); | 827 dst = setcc_r(dst, CC_Z, FLAG_Z); |
828 dst = setcc_r(dst, CC_S, FLAG_N); | |
829 } | |
808 switch (inst->extra.size) | 830 switch (inst->extra.size) |
809 { | 831 { |
810 case OPSIZE_BYTE: | 832 case OPSIZE_BYTE: |
811 dst = call(dst, (char *)m68k_write_byte); | 833 dst = call(dst, (char *)m68k_write_byte); |
812 break; | 834 break; |
841 } else if (src.mode == MODE_REG_DISPLACE8) { | 863 } else if (src.mode == MODE_REG_DISPLACE8) { |
842 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 864 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); |
843 } else { | 865 } else { |
844 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 866 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
845 } | 867 } |
846 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 868 if (inst->dst.addr_mode != MODE_AREG) { |
847 dst = setcc_r(dst, CC_Z, FLAG_Z); | 869 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
848 dst = setcc_r(dst, CC_S, FLAG_N); | 870 dst = setcc_r(dst, CC_Z, FLAG_Z); |
871 dst = setcc_r(dst, CC_S, FLAG_N); | |
872 } | |
849 switch (inst->extra.size) | 873 switch (inst->extra.size) |
850 { | 874 { |
851 case OPSIZE_BYTE: | 875 case OPSIZE_BYTE: |
852 dst = call(dst, (char *)m68k_write_byte); | 876 dst = call(dst, (char *)m68k_write_byte); |
853 break; | 877 break; |
904 } | 928 } |
905 } | 929 } |
906 if (inst->dst.params.regs.displacement) { | 930 if (inst->dst.params.regs.displacement) { |
907 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); | 931 dst = add_ir(dst, inst->dst.params.regs.displacement, SCRATCH2, SZ_D); |
908 } | 932 } |
909 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 933 if (src.mode == MODE_REG_DIRECT) { |
910 dst = setcc_r(dst, CC_Z, FLAG_Z); | 934 if (src.base != SCRATCH1) { |
911 dst = setcc_r(dst, CC_S, FLAG_N); | 935 dst = mov_rr(dst, src.base, SCRATCH1, inst->extra.size); |
936 } | |
937 } else if (src.mode == MODE_REG_DISPLACE8) { | |
938 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | |
939 } else { | |
940 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | |
941 } | |
942 if (inst->dst.addr_mode != MODE_AREG) { | |
943 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | |
944 dst = setcc_r(dst, CC_Z, FLAG_Z); | |
945 dst = setcc_r(dst, CC_S, FLAG_N); | |
946 } | |
912 switch (inst->extra.size) | 947 switch (inst->extra.size) |
913 { | 948 { |
914 case OPSIZE_BYTE: | 949 case OPSIZE_BYTE: |
915 dst = call(dst, (char *)m68k_write_byte); | 950 dst = call(dst, (char *)m68k_write_byte); |
916 break; | 951 break; |
932 } else if (src.mode == MODE_REG_DISPLACE8) { | 967 } else if (src.mode == MODE_REG_DISPLACE8) { |
933 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); | 968 dst = mov_rdisp8r(dst, src.base, src.disp, SCRATCH1, inst->extra.size); |
934 } else { | 969 } else { |
935 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 970 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
936 } | 971 } |
937 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 972 if (inst->dst.addr_mode != MODE_AREG) { |
938 dst = setcc_r(dst, CC_Z, FLAG_Z); | 973 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
939 dst = setcc_r(dst, CC_S, FLAG_N); | 974 dst = setcc_r(dst, CC_Z, FLAG_Z); |
975 dst = setcc_r(dst, CC_S, FLAG_N); | |
976 } | |
940 switch (inst->extra.size) | 977 switch (inst->extra.size) |
941 { | 978 { |
942 case OPSIZE_BYTE: | 979 case OPSIZE_BYTE: |
943 dst = call(dst, (char *)m68k_write_byte); | 980 dst = call(dst, (char *)m68k_write_byte); |
944 break; | 981 break; |
965 dst = cycles(dst, BUS*2); | 1002 dst = cycles(dst, BUS*2); |
966 } else { | 1003 } else { |
967 dst = cycles(dst, BUS); | 1004 dst = cycles(dst, BUS); |
968 } | 1005 } |
969 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); | 1006 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); |
970 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1007 if (inst->dst.addr_mode != MODE_AREG) { |
971 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1008 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
972 dst = setcc_r(dst, CC_S, FLAG_N); | 1009 dst = setcc_r(dst, CC_Z, FLAG_Z); |
1010 dst = setcc_r(dst, CC_S, FLAG_N); | |
1011 } | |
973 switch (inst->extra.size) | 1012 switch (inst->extra.size) |
974 { | 1013 { |
975 case OPSIZE_BYTE: | 1014 case OPSIZE_BYTE: |
976 dst = call(dst, (char *)m68k_write_byte); | 1015 dst = call(dst, (char *)m68k_write_byte); |
977 break; | 1016 break; |
2619 dst = add_ir(dst, src_op.disp, dst_op.base, size); | 2658 dst = add_ir(dst, src_op.disp, dst_op.base, size); |
2620 } else { | 2659 } else { |
2621 dst = add_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 2660 dst = add_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); |
2622 } | 2661 } |
2623 } | 2662 } |
2624 dst = setcc_r(dst, CC_C, FLAG_C); | 2663 if (inst->dst.addr_mode != MODE_AREG) { |
2625 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2664 dst = setcc_r(dst, CC_C, FLAG_C); |
2626 dst = setcc_r(dst, CC_S, FLAG_N); | 2665 dst = setcc_r(dst, CC_Z, FLAG_Z); |
2627 dst = setcc_r(dst, CC_O, FLAG_V); | 2666 dst = setcc_r(dst, CC_S, FLAG_N); |
2628 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2667 dst = setcc_r(dst, CC_O, FLAG_V); |
2668 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | |
2669 } | |
2629 dst = m68k_save_result(inst, dst, opts); | 2670 dst = m68k_save_result(inst, dst, opts); |
2630 break; | 2671 break; |
2631 case M68K_ADDX: | 2672 case M68K_ADDX: |
2632 dst = cycles(dst, BUS); | 2673 dst = cycles(dst, BUS); |
2633 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 2674 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); |
2645 } else { | 2686 } else { |
2646 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2687 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2647 } | 2688 } |
2648 } | 2689 } |
2649 dst = setcc_r(dst, CC_C, FLAG_C); | 2690 dst = setcc_r(dst, CC_C, FLAG_C); |
2650 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2691 dst = jcc(dst, CC_Z, dst+4); |
2692 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | |
2651 dst = setcc_r(dst, CC_S, FLAG_N); | 2693 dst = setcc_r(dst, CC_S, FLAG_N); |
2652 dst = setcc_r(dst, CC_O, FLAG_V); | 2694 dst = setcc_r(dst, CC_O, FLAG_V); |
2653 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2695 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); |
2654 dst = m68k_save_result(inst, dst, opts); | 2696 dst = m68k_save_result(inst, dst, opts); |
2655 break; | 2697 break; |
2708 } | 2750 } |
2709 } | 2751 } |
2710 break; | 2752 break; |
2711 case M68K_ASL: | 2753 case M68K_ASL: |
2712 case M68K_LSL: | 2754 case M68K_LSL: |
2755 //TODO: Check overflow flag behavior | |
2713 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shl_ir, shl_irdisp8, shl_clr, shl_clrdisp8, shr_ir, shr_irdisp8); | 2756 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, shl_ir, shl_irdisp8, shl_clr, shl_clrdisp8, shr_ir, shr_irdisp8); |
2714 break; | 2757 break; |
2715 case M68K_ASR: | 2758 case M68K_ASR: |
2716 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, sar_ir, sar_irdisp8, sar_clr, sar_clrdisp8, NULL, NULL); | 2759 dst = translate_shift(dst, inst, &src_op, &dst_op, opts, sar_ir, sar_irdisp8, sar_clr, sar_clrdisp8, NULL, NULL); |
2717 break; | 2760 break; |
3292 } | 3335 } |
3293 dst = setcc_r(dst, CC_C, FLAG_C); | 3336 dst = setcc_r(dst, CC_C, FLAG_C); |
3294 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3337 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3295 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3338 dst = setcc_r(dst, CC_Z, FLAG_Z); |
3296 dst = setcc_r(dst, CC_S, FLAG_N); | 3339 dst = setcc_r(dst, CC_S, FLAG_N); |
3340 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | |
3297 dst = m68k_save_result(inst, dst, opts); | 3341 dst = m68k_save_result(inst, dst, opts); |
3298 } else { | 3342 } else { |
3299 if (src_op.mode == MODE_IMMED) { | 3343 if (src_op.mode == MODE_IMMED) { |
3300 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); | 3344 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); |
3301 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3345 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); |
3311 } else { | 3355 } else { |
3312 dst = rcr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3356 dst = rcr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3313 } | 3357 } |
3314 } | 3358 } |
3315 dst = setcc_r(dst, CC_C, FLAG_C); | 3359 dst = setcc_r(dst, CC_C, FLAG_C); |
3360 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | |
3316 } else { | 3361 } else { |
3317 if (src_op.mode == MODE_REG_DIRECT) { | 3362 if (src_op.mode == MODE_REG_DIRECT) { |
3318 if (src_op.base != SCRATCH1) { | 3363 if (src_op.base != SCRATCH1) { |
3319 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); | 3364 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); |
3320 } | 3365 } |
3362 } else { | 3407 } else { |
3363 dst = rcr_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3408 dst = rcr_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3364 } | 3409 } |
3365 } | 3410 } |
3366 dst = setcc_r(dst, CC_C, FLAG_C); | 3411 dst = setcc_r(dst, CC_C, FLAG_C); |
3412 dst = mov_rr(dst, FLAG_C, CONTEXT, SZ_B); | |
3367 end_off = dst + 1; | 3413 end_off = dst + 1; |
3368 dst = jmp(dst, dst+2); | 3414 dst = jmp(dst, dst+2); |
3369 *zero_off = dst - (zero_off+1); | 3415 *zero_off = dst - (zero_off+1); |
3370 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3416 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL |
3417 dst = mov_rindr(dst, CONTEXT, FLAG_C, SZ_B); | |
3371 *end_off = dst - (end_off+1); | 3418 *end_off = dst - (end_off+1); |
3372 } | 3419 } |
3373 if (dst_op.mode == MODE_REG_DIRECT) { | 3420 if (dst_op.mode == MODE_REG_DIRECT) { |
3374 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3421 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3375 } else { | 3422 } else { |
3435 dst = sub_ir(dst, src_op.disp, dst_op.base, size); | 3482 dst = sub_ir(dst, src_op.disp, dst_op.base, size); |
3436 } else { | 3483 } else { |
3437 dst = sub_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 3484 dst = sub_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); |
3438 } | 3485 } |
3439 } | 3486 } |
3440 dst = setcc_r(dst, CC_C, FLAG_C); | 3487 if (inst->dst.addr_mode != MODE_AREG) { |
3441 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3488 dst = setcc_r(dst, CC_C, FLAG_C); |
3442 dst = setcc_r(dst, CC_S, FLAG_N); | 3489 dst = setcc_r(dst, CC_Z, FLAG_Z); |
3443 dst = setcc_r(dst, CC_O, FLAG_V); | 3490 dst = setcc_r(dst, CC_S, FLAG_N); |
3444 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3491 dst = setcc_r(dst, CC_O, FLAG_V); |
3492 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | |
3493 } | |
3445 dst = m68k_save_result(inst, dst, opts); | 3494 dst = m68k_save_result(inst, dst, opts); |
3446 break; | 3495 break; |
3447 case M68K_SUBX: | 3496 case M68K_SUBX: |
3448 dst = cycles(dst, BUS); | 3497 dst = cycles(dst, BUS); |
3449 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3498 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); |
3461 } else { | 3510 } else { |
3462 dst = sbb_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3511 dst = sbb_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3463 } | 3512 } |
3464 } | 3513 } |
3465 dst = setcc_r(dst, CC_C, FLAG_C); | 3514 dst = setcc_r(dst, CC_C, FLAG_C); |
3466 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3515 dst = jcc(dst, CC_Z, dst+4); |
3516 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | |
3467 dst = setcc_r(dst, CC_S, FLAG_N); | 3517 dst = setcc_r(dst, CC_S, FLAG_N); |
3468 dst = setcc_r(dst, CC_O, FLAG_V); | 3518 dst = setcc_r(dst, CC_O, FLAG_V); |
3469 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3519 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); |
3470 dst = m68k_save_result(inst, dst, opts); | 3520 dst = m68k_save_result(inst, dst, opts); |
3471 break; | 3521 break; |
3558 dst_end = opts->code_end; | 3608 dst_end = opts->code_end; |
3559 } | 3609 } |
3560 if (address >= 0x400000 && address < 0xE00000) { | 3610 if (address >= 0x400000 && address < 0xE00000) { |
3561 dst = xor_rr(dst, RDI, RDI, SZ_D); | 3611 dst = xor_rr(dst, RDI, RDI, SZ_D); |
3562 dst = call(dst, (uint8_t *)exit); | 3612 dst = call(dst, (uint8_t *)exit); |
3613 break; | |
3614 } | |
3615 uint8_t * existing = get_native_address(opts->native_code_map, address); | |
3616 if (existing) { | |
3617 dst = jmp(dst, existing); | |
3563 break; | 3618 break; |
3564 } | 3619 } |
3565 next = m68k_decode(encoded, &instbuf, address); | 3620 next = m68k_decode(encoded, &instbuf, address); |
3566 address += (next-encoded)*2; | 3621 address += (next-encoded)*2; |
3567 encoded = next; | 3622 encoded = next; |
3595 if (!ret) { | 3650 if (!ret) { |
3596 translate_m68k_stream(address, context); | 3651 translate_m68k_stream(address, context); |
3597 ret = get_native_address(context->native_code_map, address); | 3652 ret = get_native_address(context->native_code_map, address); |
3598 } | 3653 } |
3599 return ret; | 3654 return ret; |
3655 } | |
3656 | |
3657 void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler) | |
3658 { | |
3659 static uint8_t * bp_stub = NULL; | |
3660 uint8_t * native = get_native_address_trans(context, address); | |
3661 uint8_t * start_native = native; | |
3662 native = mov_ir(native, address, SCRATCH1, SZ_D); | |
3663 if (!bp_stub) { | |
3664 x86_68k_options * opts = context->options; | |
3665 uint8_t * dst = opts->cur_code; | |
3666 uint8_t * dst_end = opts->code_end; | |
3667 if (dst_end - dst < 128) { | |
3668 size_t size = 1024*1024; | |
3669 dst = alloc_code(&size); | |
3670 opts->code_end = dst_end = dst + size; | |
3671 } | |
3672 bp_stub = dst; | |
3673 native = call(native, bp_stub); | |
3674 | |
3675 //Calculate length of prologue | |
3676 dst = check_cycles_int(dst, address); | |
3677 int check_int_size = dst-bp_stub; | |
3678 dst = bp_stub; | |
3679 | |
3680 //Save context and call breakpoint handler | |
3681 dst = call(dst, (uint8_t *)m68k_save_context); | |
3682 dst = push_r(dst, SCRATCH1); | |
3683 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); | |
3684 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | |
3685 dst = call(dst, bp_handler); | |
3686 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); | |
3687 //Restore context | |
3688 dst = call(dst, (uint8_t *)m68k_load_context); | |
3689 dst = pop_r(dst, SCRATCH1); | |
3690 //do prologue stuff | |
3691 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | |
3692 uint8_t * jmp_off = dst+1; | |
3693 dst = jcc(dst, CC_NC, dst + 7); | |
3694 dst = call(dst, (uint8_t *)handle_cycle_limit_int); | |
3695 *jmp_off = dst - (jmp_off+1); | |
3696 //jump back to body of translated instruction | |
3697 dst = pop_r(dst, SCRATCH1); | |
3698 dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_Q); | |
3699 dst = jmp_r(dst, SCRATCH1); | |
3700 opts->cur_code = dst; | |
3701 } else { | |
3702 native = call(native, bp_stub); | |
3703 } | |
3704 } | |
3705 | |
3706 void remove_breakpoint(m68k_context * context, uint32_t address) | |
3707 { | |
3708 uint8_t * native = get_native_address(context->native_code_map, address); | |
3709 check_cycles_int(native, address); | |
3600 } | 3710 } |
3601 | 3711 |
3602 void start_68k_context(m68k_context * context, uint32_t address) | 3712 void start_68k_context(m68k_context * context, uint32_t address) |
3603 { | 3713 { |
3604 uint8_t * addr = get_native_address(context->native_code_map, address); | 3714 uint8_t * addr = get_native_address(context->native_code_map, address); |