Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- a/m68k_to_x86.c Tue Jul 23 23:01:03 2013 -0700 +++ b/m68k_to_x86.c Sat Oct 26 22:38:47 2013 -0700 @@ -1,3 +1,8 @@ +/* + Copyright 2013 Michael Pavone + This file is part of BlastEm. + BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. +*/ #include "gen_x86.h" #include "m68k_to_x86.h" #include "68kinst.h" @@ -123,9 +128,9 @@ //We only get one memory parameter, so if the dst operand is a register in memory, //we need to copy this to a temp register first reg = native_reg(&(inst->dst), opts); - if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) + if (reg >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) || inst->op == M68K_EXG) { - + ea->mode = MODE_REG_DISPLACE8; ea->base = CONTEXT; ea->disp = reg_offset(&(inst->src)); @@ -150,7 +155,7 @@ out = sub_irdisp8(out, dec_amount, CONTEXT, reg_offset(&(inst->src)), SZ_D); } case MODE_AREG_INDIRECT: - case MODE_AREG_POSTINC: + case MODE_AREG_POSTINC: if (opts->aregs[inst->src.params.regs.pri] >= 0) { out = mov_rr(out, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); } else { @@ -168,7 +173,7 @@ out = call(out, opts->read_32); break; } - + if (inst->src.addr_mode == MODE_AREG_POSTINC) { inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->src.params.regs.pri == 7 ? 2 : 1)); if (opts->aregs[inst->src.params.regs.pri] >= 0) { @@ -441,7 +446,7 @@ out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH2, SZ_D); } } - + if (inst->dst.addr_mode == MODE_AREG_POSTINC) { inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); if (opts->aregs[inst->dst.params.regs.pri] >= 0) { @@ -781,7 +786,7 @@ dst = mov_ir(dst, 0, FLAG_V, SZ_B); dst = mov_ir(dst, 0, FLAG_C, SZ_B); } - + if (inst->dst.addr_mode != MODE_AREG) { if (src.mode == MODE_REG_DIRECT) { flags_reg = src.base; @@ -2459,7 +2464,7 @@ dst = pop_r(dst, SCRATCH2); dst = mov_rr(dst, reg, SCRATCH1, SZ_D); dst = shr_ir(dst, 16, SCRATCH1, SZ_D); - + } else { dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+3, SCRATCH1, SZ_B); dst = push_r(dst, SCRATCH2); @@ -2527,7 +2532,7 @@ dst = push_r(dst, SCRATCH1); dst = call(dst, opts->read_8); if (reg >= 0) { - + dst = shl_ir(dst, 8, SCRATCH1, SZ_W); dst = mov_rr(dst, SCRATCH1, reg, SZ_W); dst = pop_r(dst, SCRATCH1); @@ -2628,7 +2633,7 @@ } else { dst = mov_rdisp8r(dst, src_op->base, src_op->disp, RCX, SZ_B); } - + } dst = and_ir(dst, 63, RCX, SZ_D); nz_off = dst+1; @@ -2676,7 +2681,7 @@ if (inst->extra.size == OPSIZE_LONG) { uint8_t * neq_32_off = dst + 1; dst = jcc(dst, CC_NZ, dst+2); - + //set the carry bit to the lsb if (dst_op->mode == MODE_REG_DIRECT) { dst = special(dst, 1, dst_op->base, SZ_D); @@ -2703,7 +2708,7 @@ dst = shift_irdisp8(dst, 31, dst_op->base, dst_op->disp, inst->extra.size); dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); } - + } end_off = dst+1; dst = jmp(dst, dst+2); @@ -2715,7 +2720,7 @@ } } } - + } if (!special && end_off) { *end_off = dst - (end_off + 1); @@ -2952,7 +2957,9 @@ case M68K_BCLR: case M68K_BSET: case M68K_BTST: - dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : 6); + dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : ( + inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) + ); if (src_op.mode == MODE_IMMED) { if (inst->extra.size == OPSIZE_BYTE) { src_op.disp &= 0x7; @@ -3084,7 +3091,7 @@ default: isize = 2; } - uint8_t * passed = dst+1; + uint8_t * passed = dst+1; dst = jcc(dst, CC_GE, dst+2); dst = mov_ir(dst, 1, FLAG_N, SZ_B); dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); @@ -3322,7 +3329,7 @@ } dst = call(dst, (uint8_t *)(inst->op == M68K_MOVE_SR ? set_sr : set_ccr)); dst = cycles(dst, 12); - + } break; case M68K_MOVE_USP: @@ -3446,7 +3453,7 @@ dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); } - + dst = mov_ir(dst, 0, FLAG_C, SZ_B); dst = setcc_r(dst, CC_Z, FLAG_Z); dst = setcc_r(dst, CC_S, FLAG_N); @@ -3557,6 +3564,7 @@ dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); norm_off = dst+1; dst = jcc(dst, CC_L, dst+2); + dst = sub_ir(dst, 32, SCRATCH1, SZ_B); if (dst_op.mode == MODE_REG_DIRECT) { if (inst->op == M68K_ROL) { dst = rol_ir(dst, 31, dst_op.base, inst->extra.size); @@ -3574,7 +3582,6 @@ dst = ror_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); } } - dst = sub_ir(dst, 32, SCRATCH1, SZ_B); *norm_off = dst - (norm_off+1); if (dst_op.mode == MODE_REG_DIRECT) { if (inst->op == M68K_ROL) { @@ -3781,8 +3788,38 @@ } dst = m68k_save_result(inst, dst, opts); break; - /*case M68K_STOP: - break;*/ + case M68K_STOP: { + //TODO: Trap if not in system mode + //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction + //possibly even 12 since that's how long MOVE to SR takes + dst = cycles(dst, BUS*2); + dst = mov_ir(dst, src_op.disp & 0x1, FLAG_C, SZ_B); + dst = mov_ir(dst, (src_op.disp >> 1) & 0x1, FLAG_V, SZ_B); + dst = mov_ir(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, SZ_B); + dst = mov_ir(dst, (src_op.disp >> 3) & 0x1, FLAG_N, SZ_B); + dst = mov_irind(dst, (src_op.disp >> 4) & 0x1, CONTEXT, SZ_B); + dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); + if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { + //leave supervisor mode + dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); + dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); + } + uint8_t * loop_top = dst; + dst = call(dst, (uint8_t *)do_sync); + dst = cmp_rr(dst, LIMIT, CYCLES, SZ_D); + uint8_t * normal_cycle_up = dst + 1; + dst = jcc(dst, CC_A, dst+2); + dst = cycles(dst, BUS); + uint8_t * after_cycle_up = dst + 1; + dst = jmp(dst, dst+2); + *normal_cycle_up = dst - (normal_cycle_up + 1); + dst = mov_rr(dst, LIMIT, CYCLES, SZ_D); + *after_cycle_up = dst - (after_cycle_up+1); + dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); + dst = jcc(dst, CC_C, loop_top); + break; + } case M68K_SUB: size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; dst = cycles(dst, BUS); @@ -3840,9 +3877,12 @@ dst = cycles(dst, BUS); if (src_op.mode == MODE_REG_DIRECT) { dst = rol_ir(dst, 16, src_op.base, SZ_D); + dst = cmp_ir(dst, 0, src_op.base, SZ_D); } else{ dst = rol_irdisp8(dst, 16, src_op.base, src_op.disp, SZ_D); - } + dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, SZ_D); + } + dst = mov_ir(dst, 0, FLAG_C, SZ_B); dst = setcc_r(dst, CC_Z, FLAG_Z); dst = setcc_r(dst, CC_S, FLAG_N); @@ -3912,7 +3952,7 @@ m68kinst instbuf; x86_68k_options * opts = context->options; uint8_t * dst = opts->cur_code; - uint8_t * dst_end = opts->code_end; + uint8_t * dst_end = opts->code_end; address &= 0xFFFFFF; if(get_native_address(opts->native_code_map, address)) { return dst; @@ -4040,7 +4080,7 @@ return orig_start; } } - + map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE); opts->cur_code = dst+MAX_NATIVE_SIZE; jmp(orig_start, dst); @@ -4087,12 +4127,12 @@ } bp_stub = dst; native = call(native, bp_stub); - + //Calculate length of prologue dst = check_cycles_int(dst, address, opts); int check_int_size = dst-bp_stub; dst = bp_stub; - + //Save context and call breakpoint handler dst = call(dst, (uint8_t *)m68k_save_context); dst = push_r(dst, SCRATCH1); @@ -4170,7 +4210,7 @@ ub_jcc = dst + 1; dst = jcc(dst, CC_NC, dst+2); } - + if (memmap[chunk].mask != 0xFFFFFF) { dst = and_ir(dst, memmap[chunk].mask, adr_reg, SZ_D); } @@ -4206,7 +4246,17 @@ dst = push_r(dst, CONTEXT); dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); } + dst = test_ir(dst, 8, RSP, SZ_D); + uint8_t *adjust_rsp = dst+1; + dst = jcc(dst, CC_NZ, dst+2); dst = call(dst, cfun); + uint8_t *no_adjust = dst+1; + dst = jmp(dst, dst+2); + *adjust_rsp = dst - (adjust_rsp + 1); + dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = call(dst, cfun); + dst = add_ir(dst, 8, RSP, SZ_Q); + *no_adjust = dst - (no_adjust + 1); if (is_write) { dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); } else { @@ -4214,7 +4264,7 @@ dst = mov_rr(dst, RAX, SCRATCH1, size); } dst = jmp(dst, (uint8_t *)m68k_load_context); - + *not_null = dst - (not_null + 1); } if (size == SZ_B) { @@ -4223,7 +4273,7 @@ dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_Q); if (is_write) { dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size); - + } else { dst = mov_rindr(dst, SCRATCH1, SCRATCH1, size); } @@ -4299,7 +4349,17 @@ dst = push_r(dst, CONTEXT); dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); } + dst = test_ir(dst, 8, RSP, SZ_D); + uint8_t *adjust_rsp = dst+1; + dst = jcc(dst, CC_NZ, dst+2); dst = call(dst, cfun); + uint8_t *no_adjust = dst+1; + dst = jmp(dst, dst+2); + *adjust_rsp = dst - (adjust_rsp + 1); + dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = call(dst, cfun); + dst = add_ir(dst, 8, RSP, SZ_Q); + *no_adjust = dst - (no_adjust+1); if (is_write) { dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); } else { @@ -4333,7 +4393,7 @@ void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) { - opts->flags = 0; + memset(opts, 0, sizeof(*opts)); for (int i = 0; i < 8; i++) opts->dregs[i] = opts->aregs[i] = -1; opts->dregs[0] = R10; @@ -4352,14 +4412,14 @@ opts->code_end = opts->cur_code + size; opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64); - + opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16); opts->read_8 = gen_mem_fun(opts, memmap, num_chunks, READ_8); opts->write_16 = gen_mem_fun(opts, memmap, num_chunks, WRITE_16); opts->write_8 = gen_mem_fun(opts, memmap, num_chunks, WRITE_8); - + uint8_t * dst = opts->cur_code; - + opts->read_32 = dst; dst = push_r(dst, SCRATCH1); dst = call(dst, opts->read_16); @@ -4373,7 +4433,7 @@ dst = shl_ir(dst, 16, SCRATCH2, SZ_D); dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_D); dst = retn(dst); - + opts->write_32_lowfirst = dst; dst = push_r(dst, SCRATCH2); dst = push_r(dst, SCRATCH1); @@ -4383,7 +4443,7 @@ dst = pop_r(dst, SCRATCH2); dst = shr_ir(dst, 16, SCRATCH1, SZ_D); dst = jmp(dst, opts->write_16); - + opts->write_32_highfirst = dst; dst = push_r(dst, SCRATCH1); dst = push_r(dst, SCRATCH2); @@ -4393,7 +4453,7 @@ dst = pop_r(dst, SCRATCH1); dst = add_ir(dst, 2, SCRATCH2, SZ_D); dst = jmp(dst, opts->write_16); - + opts->handle_cycle_limit_int = dst; dst = cmp_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_cycle), CYCLES, SZ_D); uint8_t * do_int = dst+1; @@ -4404,7 +4464,17 @@ dst = call(dst, (uint8_t *)m68k_save_context); dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); + dst = test_ir(dst, 8, RSP, SZ_D); + uint8_t *adjust_rsp = dst+1; + dst = jcc(dst, CC_NZ, dst+2); dst = call(dst, (uint8_t *)sync_components); + uint8_t *no_adjust = dst+1; + dst = jmp(dst, dst+2); + *adjust_rsp = dst - (adjust_rsp + 1); + dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = call(dst, (uint8_t *)sync_components); + dst = add_ir(dst, 8, RSP, SZ_Q); + *no_adjust = dst - (no_adjust+1); dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); dst = jmp(dst, (uint8_t *)m68k_load_context); *skip_sync = dst - (skip_sync+1); @@ -4445,7 +4515,7 @@ //discard function return address dst = pop_r(dst, SCRATCH2); dst = jmp_r(dst, SCRATCH1); - + opts->trap = dst; dst = push_r(dst, SCRATCH2); //swap USP and SSP if not already in supervisor mode @@ -4474,7 +4544,7 @@ dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); dst = cycles(dst, 18); dst = jmp_r(dst, SCRATCH1); - + opts->cur_code = dst; }