Mercurial > repos > blastem
comparison m68k_to_x86.c @ 487:c08a4efeee7f opengl
Update opengl branch from default. Fix build breakage unrelated to merge
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 26 Oct 2013 22:38:47 -0700 |
parents | b449af228c63 |
children | 7f54f1773e84 |
comparison
equal
deleted
inserted
replaced
449:7696d824489d | 487:c08a4efeee7f |
---|---|
1 /* | |
2 Copyright 2013 Michael Pavone | |
3 This file is part of BlastEm. | |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | |
5 */ | |
1 #include "gen_x86.h" | 6 #include "gen_x86.h" |
2 #include "m68k_to_x86.h" | 7 #include "m68k_to_x86.h" |
3 #include "68kinst.h" | 8 #include "68kinst.h" |
4 #include "mem.h" | 9 #include "mem.h" |
5 #include "x86_backend.h" | 10 #include "x86_backend.h" |
121 case MODE_REG: | 126 case MODE_REG: |
122 case MODE_AREG: | 127 case MODE_AREG: |
123 //We only get one memory parameter, so if the dst operand is a register in memory, | 128 //We only get one memory parameter, so if the dst operand is a register in memory, |
124 //we need to copy this to a temp register first | 129 //we need to copy this to a temp register first |
125 reg = native_reg(&(inst->dst), opts); | 130 reg = native_reg(&(inst->dst), opts); |
126 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) | 131 if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) |
127 || inst->op == M68K_EXG) { | 132 || inst->op == M68K_EXG) { |
128 | 133 |
129 ea->mode = MODE_REG_DISPLACE8; | 134 ea->mode = MODE_REG_DISPLACE8; |
130 ea->base = CONTEXT; | 135 ea->base = CONTEXT; |
131 ea->disp = reg_offset(&(inst->src)); | 136 ea->disp = reg_offset(&(inst->src)); |
132 } else { | 137 } else { |
133 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 138 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
148 out = sub_ir(out, dec_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); | 153 out = sub_ir(out, dec_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); |
149 } else { | 154 } else { |
150 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); | 155 out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); |
151 } | 156 } |
152 case MODE_AREG_INDIRECT: | 157 case MODE_AREG_INDIRECT: |
153 case MODE_AREG_POSTINC: | 158 case MODE_AREG_POSTINC: |
154 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 159 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
155 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); | 160 out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); |
156 } else { | 161 } else { |
157 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); | 162 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); |
158 } | 163 } |
166 break; | 171 break; |
167 case OPSIZE_LONG: | 172 case OPSIZE_LONG: |
168 out = call(out, opts->read_32); | 173 out = call(out, opts->read_32); |
169 break; | 174 break; |
170 } | 175 } |
171 | 176 |
172 if (inst->src.addr_mode == MODE_AREG_POSTINC) { | 177 if (inst->src.addr_mode == MODE_AREG_POSTINC) { |
173 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 : 1)); | 178 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 : 1)); |
174 if (opts->aregs[inst->src.params.regs.pri] >= 0) { | 179 if (opts->aregs[inst->src.params.regs.pri] >= 0) { |
175 out = add_ir(out, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); | 180 out = add_ir(out, inc_amount, opts->aregs[inst->src.params.regs.pri], SZ_D); |
176 } else { | 181 } else { |
439 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); | 444 out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH2, SZ_D); |
440 } else { | 445 } else { |
441 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); | 446 out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); |
442 } | 447 } |
443 } | 448 } |
444 | 449 |
445 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 450 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
446 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 451 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
447 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 452 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
448 out = add_ir(out, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); | 453 out = add_ir(out, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); |
449 } else { | 454 } else { |
779 if (inst->dst.addr_mode != MODE_AREG) { | 784 if (inst->dst.addr_mode != MODE_AREG) { |
780 //update statically set flags | 785 //update statically set flags |
781 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 786 dst = mov_ir(dst, 0, FLAG_V, SZ_B); |
782 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 787 dst = mov_ir(dst, 0, FLAG_C, SZ_B); |
783 } | 788 } |
784 | 789 |
785 if (inst->dst.addr_mode != MODE_AREG) { | 790 if (inst->dst.addr_mode != MODE_AREG) { |
786 if (src.mode == MODE_REG_DIRECT) { | 791 if (src.mode == MODE_REG_DIRECT) { |
787 flags_reg = src.base; | 792 flags_reg = src.base; |
788 } else { | 793 } else { |
789 if (reg >= 0) { | 794 if (reg >= 0) { |
2457 dst = push_r(dst, SCRATCH2); | 2462 dst = push_r(dst, SCRATCH2); |
2458 dst = call(dst, opts->write_8); | 2463 dst = call(dst, opts->write_8); |
2459 dst = pop_r(dst, SCRATCH2); | 2464 dst = pop_r(dst, SCRATCH2); |
2460 dst = mov_rr(dst, reg, SCRATCH1, SZ_D); | 2465 dst = mov_rr(dst, reg, SCRATCH1, SZ_D); |
2461 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); | 2466 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); |
2462 | 2467 |
2463 } else { | 2468 } else { |
2464 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+3, SCRATCH1, SZ_B); | 2469 dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+3, SCRATCH1, SZ_B); |
2465 dst = push_r(dst, SCRATCH2); | 2470 dst = push_r(dst, SCRATCH2); |
2466 dst = call(dst, opts->write_8); | 2471 dst = call(dst, opts->write_8); |
2467 dst = pop_r(dst, SCRATCH2); | 2472 dst = pop_r(dst, SCRATCH2); |
2525 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2530 dst = add_ir(dst, 2, SCRATCH1, SZ_D); |
2526 } | 2531 } |
2527 dst = push_r(dst, SCRATCH1); | 2532 dst = push_r(dst, SCRATCH1); |
2528 dst = call(dst, opts->read_8); | 2533 dst = call(dst, opts->read_8); |
2529 if (reg >= 0) { | 2534 if (reg >= 0) { |
2530 | 2535 |
2531 dst = shl_ir(dst, 8, SCRATCH1, SZ_W); | 2536 dst = shl_ir(dst, 8, SCRATCH1, SZ_W); |
2532 dst = mov_rr(dst, SCRATCH1, reg, SZ_W); | 2537 dst = mov_rr(dst, SCRATCH1, reg, SZ_W); |
2533 dst = pop_r(dst, SCRATCH1); | 2538 dst = pop_r(dst, SCRATCH1); |
2534 dst = add_ir(dst, 2, SCRATCH1, SZ_D); | 2539 dst = add_ir(dst, 2, SCRATCH1, SZ_D); |
2535 dst = call(dst, opts->read_8); | 2540 dst = call(dst, opts->read_8); |
2626 if (src_op->mode == MODE_REG_DIRECT) { | 2631 if (src_op->mode == MODE_REG_DIRECT) { |
2627 dst = mov_rr(dst, src_op->base, RCX, SZ_B); | 2632 dst = mov_rr(dst, src_op->base, RCX, SZ_B); |
2628 } else { | 2633 } else { |
2629 dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); | 2634 dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); |
2630 } | 2635 } |
2631 | 2636 |
2632 } | 2637 } |
2633 dst = and_ir(dst, 63, RCX, SZ_D); | 2638 dst = and_ir(dst, 63, RCX, SZ_D); |
2634 nz_off = dst+1; | 2639 nz_off = dst+1; |
2635 dst = jcc(dst, CC_NZ, dst+2); | 2640 dst = jcc(dst, CC_NZ, dst+2); |
2636 //Flag behavior for shift count of 0 is different for x86 than 68K | 2641 //Flag behavior for shift count of 0 is different for x86 than 68K |
2674 dst = jcc(dst, CC_L, dst+2); | 2679 dst = jcc(dst, CC_L, dst+2); |
2675 if (special) { | 2680 if (special) { |
2676 if (inst->extra.size == OPSIZE_LONG) { | 2681 if (inst->extra.size == OPSIZE_LONG) { |
2677 uint8_t * neq_32_off = dst + 1; | 2682 uint8_t * neq_32_off = dst + 1; |
2678 dst = jcc(dst, CC_NZ, dst+2); | 2683 dst = jcc(dst, CC_NZ, dst+2); |
2679 | 2684 |
2680 //set the carry bit to the lsb | 2685 //set the carry bit to the lsb |
2681 if (dst_op->mode == MODE_REG_DIRECT) { | 2686 if (dst_op->mode == MODE_REG_DIRECT) { |
2682 dst = special(dst, 1, dst_op->base, SZ_D); | 2687 dst = special(dst, 1, dst_op->base, SZ_D); |
2683 } else { | 2688 } else { |
2684 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); | 2689 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); |
2701 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2706 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2702 } else { | 2707 } else { |
2703 dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); | 2708 dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); |
2704 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2709 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2705 } | 2710 } |
2706 | 2711 |
2707 } | 2712 } |
2708 end_off = dst+1; | 2713 end_off = dst+1; |
2709 dst = jmp(dst, dst+2); | 2714 dst = jmp(dst, dst+2); |
2710 *norm_shift_off = dst - (norm_shift_off+1); | 2715 *norm_shift_off = dst - (norm_shift_off+1); |
2711 if (dst_op->mode == MODE_REG_DIRECT) { | 2716 if (dst_op->mode == MODE_REG_DIRECT) { |
2713 } else { | 2718 } else { |
2714 dst = shift_clrdisp8(dst, dst_op->base, dst_op->disp, inst->extra.size); | 2719 dst = shift_clrdisp8(dst, dst_op->base, dst_op->disp, inst->extra.size); |
2715 } | 2720 } |
2716 } | 2721 } |
2717 } | 2722 } |
2718 | 2723 |
2719 } | 2724 } |
2720 if (!special && end_off) { | 2725 if (!special && end_off) { |
2721 *end_off = dst - (end_off + 1); | 2726 *end_off = dst - (end_off + 1); |
2722 } | 2727 } |
2723 dst = setcc_r(dst, CC_C, FLAG_C); | 2728 dst = setcc_r(dst, CC_C, FLAG_C); |
2950 break; | 2955 break; |
2951 case M68K_BCHG: | 2956 case M68K_BCHG: |
2952 case M68K_BCLR: | 2957 case M68K_BCLR: |
2953 case M68K_BSET: | 2958 case M68K_BSET: |
2954 case M68K_BTST: | 2959 case M68K_BTST: |
2955 dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : 6); | 2960 dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : ( |
2961 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) | |
2962 ); | |
2956 if (src_op.mode == MODE_IMMED) { | 2963 if (src_op.mode == MODE_IMMED) { |
2957 if (inst->extra.size == OPSIZE_BYTE) { | 2964 if (inst->extra.size == OPSIZE_BYTE) { |
2958 src_op.disp &= 0x7; | 2965 src_op.disp &= 0x7; |
2959 } | 2966 } |
2960 if (inst->op == M68K_BTST) { | 2967 if (inst->op == M68K_BTST) { |
3082 isize = 6; | 3089 isize = 6; |
3083 break; | 3090 break; |
3084 default: | 3091 default: |
3085 isize = 2; | 3092 isize = 2; |
3086 } | 3093 } |
3087 uint8_t * passed = dst+1; | 3094 uint8_t * passed = dst+1; |
3088 dst = jcc(dst, CC_GE, dst+2); | 3095 dst = jcc(dst, CC_GE, dst+2); |
3089 dst = mov_ir(dst, 1, FLAG_N, SZ_B); | 3096 dst = mov_ir(dst, 1, FLAG_N, SZ_B); |
3090 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); | 3097 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); |
3091 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); | 3098 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); |
3092 dst = jmp(dst, opts->trap); | 3099 dst = jmp(dst, opts->trap); |
3320 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W); | 3327 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_W); |
3321 } | 3328 } |
3322 } | 3329 } |
3323 dst = call(dst, (uint8_t *)(inst->op == M68K_MOVE_SR ? set_sr : set_ccr)); | 3330 dst = call(dst, (uint8_t *)(inst->op == M68K_MOVE_SR ? set_sr : set_ccr)); |
3324 dst = cycles(dst, 12); | 3331 dst = cycles(dst, 12); |
3325 | 3332 |
3326 } | 3333 } |
3327 break; | 3334 break; |
3328 case M68K_MOVE_USP: | 3335 case M68K_MOVE_USP: |
3329 dst = cycles(dst, BUS); | 3336 dst = cycles(dst, BUS); |
3330 //TODO: Trap if not in supervisor mode | 3337 //TODO: Trap if not in supervisor mode |
3444 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3451 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3445 } else { | 3452 } else { |
3446 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3453 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3447 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3454 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3448 } | 3455 } |
3449 | 3456 |
3450 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3457 dst = mov_ir(dst, 0, FLAG_C, SZ_B); |
3451 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3458 dst = setcc_r(dst, CC_Z, FLAG_Z); |
3452 dst = setcc_r(dst, CC_S, FLAG_N); | 3459 dst = setcc_r(dst, CC_S, FLAG_N); |
3453 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3460 dst = mov_ir(dst, 0, FLAG_V, SZ_B); |
3454 dst = m68k_save_result(inst, dst, opts); | 3461 dst = m68k_save_result(inst, dst, opts); |
3555 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3562 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); |
3556 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3563 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); |
3557 dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); | 3564 dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); |
3558 norm_off = dst+1; | 3565 norm_off = dst+1; |
3559 dst = jcc(dst, CC_L, dst+2); | 3566 dst = jcc(dst, CC_L, dst+2); |
3567 dst = sub_ir(dst, 32, SCRATCH1, SZ_B); | |
3560 if (dst_op.mode == MODE_REG_DIRECT) { | 3568 if (dst_op.mode == MODE_REG_DIRECT) { |
3561 if (inst->op == M68K_ROL) { | 3569 if (inst->op == M68K_ROL) { |
3562 dst = rol_ir(dst, 31, dst_op.base, inst->extra.size); | 3570 dst = rol_ir(dst, 31, dst_op.base, inst->extra.size); |
3563 dst = rol_ir(dst, 1, dst_op.base, inst->extra.size); | 3571 dst = rol_ir(dst, 1, dst_op.base, inst->extra.size); |
3564 } else { | 3572 } else { |
3572 } else { | 3580 } else { |
3573 dst = ror_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); | 3581 dst = ror_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); |
3574 dst = ror_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); | 3582 dst = ror_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); |
3575 } | 3583 } |
3576 } | 3584 } |
3577 dst = sub_ir(dst, 32, SCRATCH1, SZ_B); | |
3578 *norm_off = dst - (norm_off+1); | 3585 *norm_off = dst - (norm_off+1); |
3579 if (dst_op.mode == MODE_REG_DIRECT) { | 3586 if (dst_op.mode == MODE_REG_DIRECT) { |
3580 if (inst->op == M68K_ROL) { | 3587 if (inst->op == M68K_ROL) { |
3581 dst = rol_clr(dst, dst_op.base, inst->extra.size); | 3588 dst = rol_clr(dst, dst_op.base, inst->extra.size); |
3582 } else { | 3589 } else { |
3779 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); | 3786 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); |
3780 } | 3787 } |
3781 } | 3788 } |
3782 dst = m68k_save_result(inst, dst, opts); | 3789 dst = m68k_save_result(inst, dst, opts); |
3783 break; | 3790 break; |
3784 /*case M68K_STOP: | 3791 case M68K_STOP: { |
3785 break;*/ | 3792 //TODO: Trap if not in system mode |
3793 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction | |
3794 //possibly even 12 since that's how long MOVE to SR takes | |
3795 dst = cycles(dst, BUS*2); | |
3796 dst = mov_ir(dst, src_op.disp & 0x1, FLAG_C, SZ_B); | |
3797 dst = mov_ir(dst, (src_op.disp >> 1) & 0x1, FLAG_V, SZ_B); | |
3798 dst = mov_ir(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, SZ_B); | |
3799 dst = mov_ir(dst, (src_op.disp >> 3) & 0x1, FLAG_N, SZ_B); | |
3800 dst = mov_irind(dst, (src_op.disp >> 4) & 0x1, CONTEXT, SZ_B); | |
3801 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); | |
3802 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | |
3803 //leave supervisor mode | |
3804 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | |
3805 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); | |
3806 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); | |
3807 } | |
3808 uint8_t * loop_top = dst; | |
3809 dst = call(dst, (uint8_t *)do_sync); | |
3810 dst = cmp_rr(dst, LIMIT, CYCLES, SZ_D); | |
3811 uint8_t * normal_cycle_up = dst + 1; | |
3812 dst = jcc(dst, CC_A, dst+2); | |
3813 dst = cycles(dst, BUS); | |
3814 uint8_t * after_cycle_up = dst + 1; | |
3815 dst = jmp(dst, dst+2); | |
3816 *normal_cycle_up = dst - (normal_cycle_up + 1); | |
3817 dst = mov_rr(dst, LIMIT, CYCLES, SZ_D); | |
3818 *after_cycle_up = dst - (after_cycle_up+1); | |
3819 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); | |
3820 dst = jcc(dst, CC_C, loop_top); | |
3821 break; | |
3822 } | |
3786 case M68K_SUB: | 3823 case M68K_SUB: |
3787 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; | 3824 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; |
3788 dst = cycles(dst, BUS); | 3825 dst = cycles(dst, BUS); |
3789 if (src_op.mode == MODE_REG_DIRECT) { | 3826 if (src_op.mode == MODE_REG_DIRECT) { |
3790 if (dst_op.mode == MODE_REG_DIRECT) { | 3827 if (dst_op.mode == MODE_REG_DIRECT) { |
3838 break; | 3875 break; |
3839 case M68K_SWAP: | 3876 case M68K_SWAP: |
3840 dst = cycles(dst, BUS); | 3877 dst = cycles(dst, BUS); |
3841 if (src_op.mode == MODE_REG_DIRECT) { | 3878 if (src_op.mode == MODE_REG_DIRECT) { |
3842 dst = rol_ir(dst, 16, src_op.base, SZ_D); | 3879 dst = rol_ir(dst, 16, src_op.base, SZ_D); |
3880 dst = cmp_ir(dst, 0, src_op.base, SZ_D); | |
3843 } else{ | 3881 } else{ |
3844 dst = rol_irdisp8(dst, 16, src_op.base, src_op.disp, SZ_D); | 3882 dst = rol_irdisp8(dst, 16, src_op.base, src_op.disp, SZ_D); |
3845 } | 3883 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, SZ_D); |
3884 } | |
3885 | |
3846 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3886 dst = mov_ir(dst, 0, FLAG_C, SZ_B); |
3847 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3887 dst = setcc_r(dst, CC_Z, FLAG_Z); |
3848 dst = setcc_r(dst, CC_S, FLAG_N); | 3888 dst = setcc_r(dst, CC_S, FLAG_N); |
3849 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3889 dst = mov_ir(dst, 0, FLAG_V, SZ_B); |
3850 break; | 3890 break; |
3910 uint8_t * translate_m68k_stream(uint32_t address, m68k_context * context) | 3950 uint8_t * translate_m68k_stream(uint32_t address, m68k_context * context) |
3911 { | 3951 { |
3912 m68kinst instbuf; | 3952 m68kinst instbuf; |
3913 x86_68k_options * opts = context->options; | 3953 x86_68k_options * opts = context->options; |
3914 uint8_t * dst = opts->cur_code; | 3954 uint8_t * dst = opts->cur_code; |
3915 uint8_t * dst_end = opts->code_end; | 3955 uint8_t * dst_end = opts->code_end; |
3916 address &= 0xFFFFFF; | 3956 address &= 0xFFFFFF; |
3917 if(get_native_address(opts->native_code_map, address)) { | 3957 if(get_native_address(opts->native_code_map, address)) { |
3918 return dst; | 3958 return dst; |
3919 } | 3959 } |
3920 char disbuf[1024]; | 3960 char disbuf[1024]; |
4038 } | 4078 } |
4039 m68k_handle_deferred(context); | 4079 m68k_handle_deferred(context); |
4040 return orig_start; | 4080 return orig_start; |
4041 } | 4081 } |
4042 } | 4082 } |
4043 | 4083 |
4044 map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE); | 4084 map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE); |
4045 opts->cur_code = dst+MAX_NATIVE_SIZE; | 4085 opts->cur_code = dst+MAX_NATIVE_SIZE; |
4046 jmp(orig_start, dst); | 4086 jmp(orig_start, dst); |
4047 if (!m68k_is_terminal(&instbuf)) { | 4087 if (!m68k_is_terminal(&instbuf)) { |
4048 jmp(native_end, get_native_address_trans(context, orig + (after-inst)*2)); | 4088 jmp(native_end, get_native_address_trans(context, orig + (after-inst)*2)); |
4085 dst = alloc_code(&size); | 4125 dst = alloc_code(&size); |
4086 opts->code_end = dst_end = dst + size; | 4126 opts->code_end = dst_end = dst + size; |
4087 } | 4127 } |
4088 bp_stub = dst; | 4128 bp_stub = dst; |
4089 native = call(native, bp_stub); | 4129 native = call(native, bp_stub); |
4090 | 4130 |
4091 //Calculate length of prologue | 4131 //Calculate length of prologue |
4092 dst = check_cycles_int(dst, address, opts); | 4132 dst = check_cycles_int(dst, address, opts); |
4093 int check_int_size = dst-bp_stub; | 4133 int check_int_size = dst-bp_stub; |
4094 dst = bp_stub; | 4134 dst = bp_stub; |
4095 | 4135 |
4096 //Save context and call breakpoint handler | 4136 //Save context and call breakpoint handler |
4097 dst = call(dst, (uint8_t *)m68k_save_context); | 4137 dst = call(dst, (uint8_t *)m68k_save_context); |
4098 dst = push_r(dst, SCRATCH1); | 4138 dst = push_r(dst, SCRATCH1); |
4099 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); | 4139 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); |
4100 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | 4140 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); |
4168 if (memmap[chunk].end < 0x1000000) { | 4208 if (memmap[chunk].end < 0x1000000) { |
4169 dst = cmp_ir(dst, memmap[chunk].end, adr_reg, SZ_D); | 4209 dst = cmp_ir(dst, memmap[chunk].end, adr_reg, SZ_D); |
4170 ub_jcc = dst + 1; | 4210 ub_jcc = dst + 1; |
4171 dst = jcc(dst, CC_NC, dst+2); | 4211 dst = jcc(dst, CC_NC, dst+2); |
4172 } | 4212 } |
4173 | 4213 |
4174 if (memmap[chunk].mask != 0xFFFFFF) { | 4214 if (memmap[chunk].mask != 0xFFFFFF) { |
4175 dst = and_ir(dst, memmap[chunk].mask, adr_reg, SZ_D); | 4215 dst = and_ir(dst, memmap[chunk].mask, adr_reg, SZ_D); |
4176 } | 4216 } |
4177 void * cfun; | 4217 void * cfun; |
4178 switch (fun_type) | 4218 switch (fun_type) |
4204 dst = mov_rr(dst, SCRATCH1, RDX, size); | 4244 dst = mov_rr(dst, SCRATCH1, RDX, size); |
4205 } else { | 4245 } else { |
4206 dst = push_r(dst, CONTEXT); | 4246 dst = push_r(dst, CONTEXT); |
4207 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); | 4247 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); |
4208 } | 4248 } |
4249 dst = test_ir(dst, 8, RSP, SZ_D); | |
4250 uint8_t *adjust_rsp = dst+1; | |
4251 dst = jcc(dst, CC_NZ, dst+2); | |
4209 dst = call(dst, cfun); | 4252 dst = call(dst, cfun); |
4253 uint8_t *no_adjust = dst+1; | |
4254 dst = jmp(dst, dst+2); | |
4255 *adjust_rsp = dst - (adjust_rsp + 1); | |
4256 dst = sub_ir(dst, 8, RSP, SZ_Q); | |
4257 dst = call(dst, cfun); | |
4258 dst = add_ir(dst, 8, RSP, SZ_Q); | |
4259 *no_adjust = dst - (no_adjust + 1); | |
4210 if (is_write) { | 4260 if (is_write) { |
4211 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); | 4261 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); |
4212 } else { | 4262 } else { |
4213 dst = pop_r(dst, CONTEXT); | 4263 dst = pop_r(dst, CONTEXT); |
4214 dst = mov_rr(dst, RAX, SCRATCH1, size); | 4264 dst = mov_rr(dst, RAX, SCRATCH1, size); |
4215 } | 4265 } |
4216 dst = jmp(dst, (uint8_t *)m68k_load_context); | 4266 dst = jmp(dst, (uint8_t *)m68k_load_context); |
4217 | 4267 |
4218 *not_null = dst - (not_null + 1); | 4268 *not_null = dst - (not_null + 1); |
4219 } | 4269 } |
4220 if (size == SZ_B) { | 4270 if (size == SZ_B) { |
4221 dst = xor_ir(dst, 1, adr_reg, SZ_D); | 4271 dst = xor_ir(dst, 1, adr_reg, SZ_D); |
4222 } | 4272 } |
4223 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_Q); | 4273 dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_Q); |
4224 if (is_write) { | 4274 if (is_write) { |
4225 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size); | 4275 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size); |
4226 | 4276 |
4227 } else { | 4277 } else { |
4228 dst = mov_rindr(dst, SCRATCH1, SCRATCH1, size); | 4278 dst = mov_rindr(dst, SCRATCH1, SCRATCH1, size); |
4229 } | 4279 } |
4230 } else { | 4280 } else { |
4231 uint8_t tmp_size = size; | 4281 uint8_t tmp_size = size; |
4297 dst = mov_rr(dst, SCRATCH1, RDX, size); | 4347 dst = mov_rr(dst, SCRATCH1, RDX, size); |
4298 } else { | 4348 } else { |
4299 dst = push_r(dst, CONTEXT); | 4349 dst = push_r(dst, CONTEXT); |
4300 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); | 4350 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); |
4301 } | 4351 } |
4352 dst = test_ir(dst, 8, RSP, SZ_D); | |
4353 uint8_t *adjust_rsp = dst+1; | |
4354 dst = jcc(dst, CC_NZ, dst+2); | |
4302 dst = call(dst, cfun); | 4355 dst = call(dst, cfun); |
4356 uint8_t *no_adjust = dst+1; | |
4357 dst = jmp(dst, dst+2); | |
4358 *adjust_rsp = dst - (adjust_rsp + 1); | |
4359 dst = sub_ir(dst, 8, RSP, SZ_Q); | |
4360 dst = call(dst, cfun); | |
4361 dst = add_ir(dst, 8, RSP, SZ_Q); | |
4362 *no_adjust = dst - (no_adjust+1); | |
4303 if (is_write) { | 4363 if (is_write) { |
4304 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); | 4364 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); |
4305 } else { | 4365 } else { |
4306 dst = pop_r(dst, CONTEXT); | 4366 dst = pop_r(dst, CONTEXT); |
4307 dst = mov_rr(dst, RAX, SCRATCH1, size); | 4367 dst = mov_rr(dst, RAX, SCRATCH1, size); |
4331 return start; | 4391 return start; |
4332 } | 4392 } |
4333 | 4393 |
4334 void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) | 4394 void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) |
4335 { | 4395 { |
4336 opts->flags = 0; | 4396 memset(opts, 0, sizeof(*opts)); |
4337 for (int i = 0; i < 8; i++) | 4397 for (int i = 0; i < 8; i++) |
4338 opts->dregs[i] = opts->aregs[i] = -1; | 4398 opts->dregs[i] = opts->aregs[i] = -1; |
4339 opts->dregs[0] = R10; | 4399 opts->dregs[0] = R10; |
4340 opts->dregs[1] = R11; | 4400 opts->dregs[1] = R11; |
4341 opts->dregs[2] = R12; | 4401 opts->dregs[2] = R12; |
4350 size_t size = 1024 * 1024; | 4410 size_t size = 1024 * 1024; |
4351 opts->cur_code = alloc_code(&size); | 4411 opts->cur_code = alloc_code(&size); |
4352 opts->code_end = opts->cur_code + size; | 4412 opts->code_end = opts->cur_code + size; |
4353 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); | 4413 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); |
4354 memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64); | 4414 memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64); |
4355 | 4415 |
4356 opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16); | 4416 opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16); |
4357 opts->read_8 = gen_mem_fun(opts, memmap, num_chunks, READ_8); | 4417 opts->read_8 = gen_mem_fun(opts, memmap, num_chunks, READ_8); |
4358 opts->write_16 = gen_mem_fun(opts, memmap, num_chunks, WRITE_16); | 4418 opts->write_16 = gen_mem_fun(opts, memmap, num_chunks, WRITE_16); |
4359 opts->write_8 = gen_mem_fun(opts, memmap, num_chunks, WRITE_8); | 4419 opts->write_8 = gen_mem_fun(opts, memmap, num_chunks, WRITE_8); |
4360 | 4420 |
4361 uint8_t * dst = opts->cur_code; | 4421 uint8_t * dst = opts->cur_code; |
4362 | 4422 |
4363 opts->read_32 = dst; | 4423 opts->read_32 = dst; |
4364 dst = push_r(dst, SCRATCH1); | 4424 dst = push_r(dst, SCRATCH1); |
4365 dst = call(dst, opts->read_16); | 4425 dst = call(dst, opts->read_16); |
4366 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); | 4426 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); |
4367 dst = pop_r(dst, SCRATCH1); | 4427 dst = pop_r(dst, SCRATCH1); |
4371 dst = pop_r(dst, SCRATCH2); | 4431 dst = pop_r(dst, SCRATCH2); |
4372 dst = movzx_rr(dst, SCRATCH1, SCRATCH1, SZ_W, SZ_D); | 4432 dst = movzx_rr(dst, SCRATCH1, SCRATCH1, SZ_W, SZ_D); |
4373 dst = shl_ir(dst, 16, SCRATCH2, SZ_D); | 4433 dst = shl_ir(dst, 16, SCRATCH2, SZ_D); |
4374 dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_D); | 4434 dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_D); |
4375 dst = retn(dst); | 4435 dst = retn(dst); |
4376 | 4436 |
4377 opts->write_32_lowfirst = dst; | 4437 opts->write_32_lowfirst = dst; |
4378 dst = push_r(dst, SCRATCH2); | 4438 dst = push_r(dst, SCRATCH2); |
4379 dst = push_r(dst, SCRATCH1); | 4439 dst = push_r(dst, SCRATCH1); |
4380 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 4440 dst = add_ir(dst, 2, SCRATCH2, SZ_D); |
4381 dst = call(dst, opts->write_16); | 4441 dst = call(dst, opts->write_16); |
4382 dst = pop_r(dst, SCRATCH1); | 4442 dst = pop_r(dst, SCRATCH1); |
4383 dst = pop_r(dst, SCRATCH2); | 4443 dst = pop_r(dst, SCRATCH2); |
4384 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); | 4444 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); |
4385 dst = jmp(dst, opts->write_16); | 4445 dst = jmp(dst, opts->write_16); |
4386 | 4446 |
4387 opts->write_32_highfirst = dst; | 4447 opts->write_32_highfirst = dst; |
4388 dst = push_r(dst, SCRATCH1); | 4448 dst = push_r(dst, SCRATCH1); |
4389 dst = push_r(dst, SCRATCH2); | 4449 dst = push_r(dst, SCRATCH2); |
4390 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); | 4450 dst = shr_ir(dst, 16, SCRATCH1, SZ_D); |
4391 dst = call(dst, opts->write_16); | 4451 dst = call(dst, opts->write_16); |
4392 dst = pop_r(dst, SCRATCH2); | 4452 dst = pop_r(dst, SCRATCH2); |
4393 dst = pop_r(dst, SCRATCH1); | 4453 dst = pop_r(dst, SCRATCH1); |
4394 dst = add_ir(dst, 2, SCRATCH2, SZ_D); | 4454 dst = add_ir(dst, 2, SCRATCH2, SZ_D); |
4395 dst = jmp(dst, opts->write_16); | 4455 dst = jmp(dst, opts->write_16); |
4396 | 4456 |
4397 opts->handle_cycle_limit_int = dst; | 4457 opts->handle_cycle_limit_int = dst; |
4398 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); | 4458 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); |
4399 uint8_t * do_int = dst+1; | 4459 uint8_t * do_int = dst+1; |
4400 dst = jcc(dst, CC_NC, dst+2); | 4460 dst = jcc(dst, CC_NC, dst+2); |
4401 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); | 4461 dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, sync_cycle), CYCLES, SZ_D); |
4402 uint8_t * skip_sync = dst+1; | 4462 uint8_t * skip_sync = dst+1; |
4403 dst = jcc(dst, CC_C, dst+2); | 4463 dst = jcc(dst, CC_C, dst+2); |
4404 dst = call(dst, (uint8_t *)m68k_save_context); | 4464 dst = call(dst, (uint8_t *)m68k_save_context); |
4405 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); | 4465 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); |
4406 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); | 4466 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); |
4467 dst = test_ir(dst, 8, RSP, SZ_D); | |
4468 uint8_t *adjust_rsp = dst+1; | |
4469 dst = jcc(dst, CC_NZ, dst+2); | |
4407 dst = call(dst, (uint8_t *)sync_components); | 4470 dst = call(dst, (uint8_t *)sync_components); |
4471 uint8_t *no_adjust = dst+1; | |
4472 dst = jmp(dst, dst+2); | |
4473 *adjust_rsp = dst - (adjust_rsp + 1); | |
4474 dst = sub_ir(dst, 8, RSP, SZ_Q); | |
4475 dst = call(dst, (uint8_t *)sync_components); | |
4476 dst = add_ir(dst, 8, RSP, SZ_Q); | |
4477 *no_adjust = dst - (no_adjust+1); | |
4408 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); | 4478 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); |
4409 dst = jmp(dst, (uint8_t *)m68k_load_context); | 4479 dst = jmp(dst, (uint8_t *)m68k_load_context); |
4410 *skip_sync = dst - (skip_sync+1); | 4480 *skip_sync = dst - (skip_sync+1); |
4411 dst = retn(dst); | 4481 dst = retn(dst); |
4412 *do_int = dst - (do_int+1); | 4482 *do_int = dst - (do_int+1); |
4443 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); | 4513 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); |
4444 dst = cycles(dst, 24); | 4514 dst = cycles(dst, 24); |
4445 //discard function return address | 4515 //discard function return address |
4446 dst = pop_r(dst, SCRATCH2); | 4516 dst = pop_r(dst, SCRATCH2); |
4447 dst = jmp_r(dst, SCRATCH1); | 4517 dst = jmp_r(dst, SCRATCH1); |
4448 | 4518 |
4449 opts->trap = dst; | 4519 opts->trap = dst; |
4450 dst = push_r(dst, SCRATCH2); | 4520 dst = push_r(dst, SCRATCH2); |
4451 //swap USP and SSP if not already in supervisor mode | 4521 //swap USP and SSP if not already in supervisor mode |
4452 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); | 4522 dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); |
4453 already_supervisor = dst+1; | 4523 already_supervisor = dst+1; |
4472 dst = shl_ir(dst, 2, SCRATCH1, SZ_D); | 4542 dst = shl_ir(dst, 2, SCRATCH1, SZ_D); |
4473 dst = call(dst, opts->read_32); | 4543 dst = call(dst, opts->read_32); |
4474 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); | 4544 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); |
4475 dst = cycles(dst, 18); | 4545 dst = cycles(dst, 18); |
4476 dst = jmp_r(dst, SCRATCH1); | 4546 dst = jmp_r(dst, SCRATCH1); |
4477 | 4547 |
4478 opts->cur_code = dst; | 4548 opts->cur_code = dst; |
4479 } | 4549 } |
4480 | 4550 |
4481 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) | 4551 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) |
4482 { | 4552 { |