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);