# HG changeset patch # User Michael Pavone # Date 1393913840 28800 # Node ID 1594525e2157bd65542bca1206d9832017ef78dd # Parent 29d99db6f55d6b67c01d5e63df70543de1b3902c More 68K core refactoring to both reduce the amount of code and better split the host-cpu specific parts from the generic parts diff -r 29d99db6f55d -r 1594525e2157 gen.h --- a/gen.h Mon Mar 03 22:16:41 2014 -0800 +++ b/gen.h Mon Mar 03 22:17:20 2014 -0800 @@ -20,5 +20,6 @@ void init_code_info(code_info *code); void call(code_info *code, code_ptr fun); void jmp(code_info *code, code_ptr dest); +void jmp_r(code_info *code, uint8_t dst); #endif //GEN_H_ diff -r 29d99db6f55d -r 1594525e2157 m68k_core.c --- a/m68k_core.c Mon Mar 03 22:16:41 2014 -0800 +++ b/m68k_core.c Mon Mar 03 22:17:20 2014 -0800 @@ -13,6 +13,8 @@ #include #include +char disasm_buf[1024]; + int8_t native_reg(m68k_op_info * op, m68k_options * opts) { if (op->addr_mode == MODE_REG) { @@ -24,13 +26,20 @@ return -1; } +size_t dreg_offset(uint8_t reg) +{ + return offsetof(m68k_context, dregs) + sizeof(uint32_t) * reg; +} + +size_t areg_offset(uint8_t reg) +{ + return offsetof(m68k_context, aregs) + sizeof(uint32_t) * reg; +} + //must be called with an m68k_op_info that uses a register size_t reg_offset(m68k_op_info *op) { - if (op->addr_mode == MODE_REG) { - return offsetof(m68k_context, dregs) + sizeof(uint32_t) * op->params.regs.pri; - } - return offsetof(m68k_context, aregs) + sizeof(uint32_t) * op->params.regs.pri; + return op->addr_mode == MODE_REG ? dreg_offset(op->params.regs.pri) : areg_offset(op->params.regs.pri); } void print_regs_exit(m68k_context * context) @@ -77,6 +86,281 @@ } } +void translate_m68k_lea(m68k_options * opts, m68kinst * inst) +{ + code_info *code = &opts->gen.code; + int8_t dst_reg = native_reg(&(inst->dst), opts); + switch(inst->src.addr_mode) + { + case MODE_AREG_INDIRECT: + cycles(&opts->gen, BUS); + if (dst_reg >= 0) { + areg_to_native(opts, inst->src.params.regs.pri, dst_reg); + } else { + if (opts->aregs[inst->src.params.regs.pri] >= 0) { + native_to_areg(opts, opts->aregs[inst->src.params.regs.pri], inst->dst.params.regs.pri); + } else { + areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1); + native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri); + } + } + break; + case MODE_AREG_DISPLACE: + cycles(&opts->gen, 8); + calc_areg_displace(opts, &inst->src, dst_reg >= 0 ? dst_reg : opts->gen.scratch1); + if (dst_reg < 0) { + native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri); + } + break; + case MODE_AREG_INDEX_DISP8: + cycles(&opts->gen, 12); + if (dst_reg < 0 || inst->dst.params.regs.pri == inst->src.params.regs.pri || inst->dst.params.regs.pri == (inst->src.params.regs.sec >> 1 & 0x7)) { + dst_reg = opts->gen.scratch1; + } + calc_areg_index_disp8(opts, &inst->src, dst_reg); + if (dst_reg == opts->gen.scratch1) { + native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri); + } + break; + case MODE_PC_DISPLACE: + cycles(&opts->gen, 8); + ldi_areg(opts, inst->src.params.regs.displacement + inst->address+2, inst->dst.params.regs.pri); + break; + case MODE_PC_INDEX_DISP8: + cycles(&opts->gen, BUS*3); + if (dst_reg < 0 || inst->dst.params.regs.pri == (inst->src.params.regs.sec >> 1 & 0x7)) { + dst_reg = opts->gen.scratch1; + } + ldi_native(opts, inst->address+2, dst_reg); + calc_index_disp8(opts, &inst->src, dst_reg); + if (dst_reg == opts->gen.scratch1) { + native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri); + } + break; + case MODE_ABSOLUTE: + case MODE_ABSOLUTE_SHORT: + cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); + ldi_areg(opts, inst->src.params.immed, inst->dst.params.regs.pri); + break; + default: + m68k_disasm(inst, disasm_buf); + printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); + exit(1); + } +} + +void translate_m68k_pea(m68k_options * opts, m68kinst * inst) +{ + code_info *code = &opts->gen.code; + switch(inst->src.addr_mode) + { + case MODE_AREG_INDIRECT: + cycles(&opts->gen, BUS); + areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1); + break; + case MODE_AREG_DISPLACE: + cycles(&opts->gen, 8); + calc_areg_displace(opts, &inst->src, opts->gen.scratch1); + break; + case MODE_AREG_INDEX_DISP8: + cycles(&opts->gen, 6);//TODO: Check to make sure this is correct + calc_areg_index_disp8(opts, &inst->src, opts->gen.scratch1); + break; + case MODE_PC_DISPLACE: + cycles(&opts->gen, 8); + ldi_native(opts, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1); + break; + case MODE_PC_INDEX_DISP8: + cycles(&opts->gen, BUS*3);//TODO: Check to make sure this is correct + ldi_native(opts, inst->address+2, opts->gen.scratch1); + calc_index_disp8(opts, &inst->src, opts->gen.scratch1); + break; + case MODE_ABSOLUTE: + case MODE_ABSOLUTE_SHORT: + cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); + ldi_native(opts, inst->src.params.immed, opts->gen.scratch1); + break; + default: + m68k_disasm(inst, disasm_buf); + printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); + exit(1); + } + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_32_lowfirst); +} + +void push_const(m68k_options *opts, int32_t value) +{ + ldi_native(opts, value, opts->gen.scratch1); + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + call(&opts->gen.code, opts->write_32_highfirst); +} + +void jump_m68k_abs(m68k_options * opts, uint32_t address) +{ + code_info *code = &opts->gen.code; + code_ptr dest_addr = get_native_address(opts->gen.native_code_map, address); + if (!dest_addr) { + opts->gen.deferred = defer_address(opts->gen.deferred, address, code->cur + 1); + //dummy address to be replaced later, make sure it generates a 4-byte displacement + dest_addr = code->cur + 256; + } + jmp(code, dest_addr); + //this used to call opts->native_addr for destinations in RAM, but that shouldn't be needed + //since instruction retranslation patches the original native instruction location +} + +void translate_m68k_bsr(m68k_options * opts, m68kinst * inst) +{ + code_info *code = &opts->gen.code; + int32_t disp = inst->src.params.immed; + uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : 4); + //TODO: Add cycles in the right place relative to pushing the return address on the stack + cycles(&opts->gen, 10); + push_const(opts, after); + jump_m68k_abs(opts, inst->address + 2 + disp); +} + +void translate_m68k_jmp_jsr(m68k_options * opts, m68kinst * inst) +{ + uint8_t is_jsr = inst->op == M68K_JSR; + code_info *code = &opts->gen.code; + code_ptr dest_addr; + uint8_t sec_reg; + uint32_t after; + uint32_t m68k_addr; + switch(inst->src.addr_mode) + { + case MODE_AREG_INDIRECT: + cycles(&opts->gen, BUS*2); + if (is_jsr) { + push_const(opts, inst->address+2); + } + areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1); + call(code, opts->native_addr); + jmp_r(code, opts->gen.scratch1); + break; + case MODE_AREG_DISPLACE: + cycles(&opts->gen, BUS*2); + if (is_jsr) { + push_const(opts, inst->address+4); + } + calc_areg_displace(opts, &inst->src, opts->gen.scratch1); + call(code, opts->native_addr); + jmp_r(code, opts->gen.scratch1); + break; + case MODE_AREG_INDEX_DISP8: + cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct + if (is_jsr) { + push_const(opts, inst->address+4); + } + calc_areg_index_disp8(opts, &inst->src, opts->gen.scratch1); + call(code, opts->native_addr); + jmp_r(code, opts->gen.scratch1); + break; + case MODE_PC_DISPLACE: + //TODO: Add cycles in the right place relative to pushing the return address on the stack + cycles(&opts->gen, 10); + if (is_jsr) { + push_const(opts, inst->address+4); + } + jump_m68k_abs(opts, inst->src.params.regs.displacement + inst->address + 2); + break; + case MODE_PC_INDEX_DISP8: + cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct + if (is_jsr) { + push_const(opts, inst->address+4); + } + ldi_native(opts, inst->address+2, opts->gen.scratch1); + calc_index_disp8(opts, &inst->src, opts->gen.scratch1); + call(code, opts->native_addr); + jmp_r(code, opts->gen.scratch1); + break; + case MODE_ABSOLUTE: + case MODE_ABSOLUTE_SHORT: + //TODO: Add cycles in the right place relative to pushing the return address on the stack + cycles(&opts->gen, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); + if (is_jsr) { + push_const(opts, inst->address + (inst->src.addr_mode == MODE_ABSOLUTE ? 6 : 4)); + } + jump_m68k_abs(opts, inst->src.params.immed); + break; + default: + m68k_disasm(inst, disasm_buf); + printf("%s\naddress mode %d not yet supported (%s)\n", disasm_buf, inst->src.addr_mode, is_jsr ? "jsr" : "jmp"); + exit(1); + } +} + +void translate_m68k_unlk(m68k_options * opts, m68kinst * inst) +{ + cycles(&opts->gen, BUS); + areg_to_native(opts, inst->dst.params.regs.pri, opts->aregs[7]); + areg_to_native(opts, 7, opts->gen.scratch1); + call(&opts->gen.code, opts->read_32); + native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri); + addi_areg(opts, 4, 7); +} + +void translate_m68k_link(m68k_options * opts, m68kinst * inst) +{ + //compensate for displacement word + cycles(&opts->gen, BUS); + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1); + call(&opts->gen.code, opts->write_32_highfirst); + native_to_areg(opts, opts->aregs[7], inst->src.params.regs.pri); + addi_areg(opts, inst->dst.params.immed, 7); + //prefetch + cycles(&opts->gen, BUS); +} + +void translate_m68k_rts(m68k_options * opts, m68kinst * inst) +{ + code_info *code = &opts->gen.code; + //TODO: Add cycles + areg_to_native(opts, 7, opts->gen.scratch1); + addi_areg(opts, 4, 7); + call(code, opts->read_32); + call(code, opts->native_addr); + jmp_r(code, opts->gen.scratch1); +} + +void translate_m68k_rtr(m68k_options *opts, m68kinst * inst) +{ + code_info *code = &opts->gen.code; + //Read saved CCR + areg_to_native(opts, 7, opts->gen.scratch1); + call(code, opts->read_16); + addi_areg(opts, 2, 7); + call(code, opts->set_ccr); + //Read saved PC + areg_to_native(opts, 7, opts->gen.scratch1); + call(code, opts->read_32); + addi_areg(opts, 4, 7); + //Get native address and jump to it + call(code, opts->native_addr); + jmp_r(code, opts->gen.scratch1); +} + +void translate_m68k_trap(m68k_options *opts, m68kinst *inst) +{ + code_info *code = &opts->gen.code; + ldi_native(opts, inst->src.params.immed + VECTOR_TRAP_0, opts->gen.scratch2); + ldi_native(opts, inst->address+2, opts->gen.scratch1); + jmp(code, opts->trap); +} + +void swap_ssp_usp(m68k_options * opts) +{ + areg_to_native(opts, 7, opts->gen.scratch2); + areg_to_native(opts, 8, opts->aregs[7]); + native_to_areg(opts, opts->gen.scratch2, 8); +} + code_ptr get_native_address(native_map_slot * native_code_map, uint32_t address) { address &= 0xFFFFFF; @@ -278,3 +562,12 @@ start_68k_context(context, address); } + +void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) +{ + memset(context, 0, sizeof(m68k_context)); + context->native_code_map = native_code_map; + context->options = opts; + context->int_cycle = 0xFFFFFFFF; + context->status = 0x27; +} diff -r 29d99db6f55d -r 1594525e2157 m68k_core_x86.c --- a/m68k_core_x86.c Mon Mar 03 22:16:41 2014 -0800 +++ b/m68k_core_x86.c Mon Mar 03 22:17:20 2014 -0800 @@ -14,9 +14,6 @@ #include #include -#define BUS 4 -#define PREDEC_PENALTY 2 - #define CYCLES RAX #define LIMIT RBP #define CONTEXT RSI @@ -36,15 +33,6 @@ FLAG_C }; -char disasm_buf[1024]; - -m68k_context * sync_components(m68k_context * context, uint32_t address); - -void m68k_invalid(); -void bcd_add(); -void bcd_sub(); - - void set_flag(m68k_options * opts, uint8_t val, uint8_t flag) { if (opts->flag_regs[flag] >= 0) { @@ -181,6 +169,145 @@ } } +void areg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) +{ + if (opts->aregs[reg] >= 0) { + mov_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D); + } else { + mov_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_D); + } +} + +void dreg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) +{ + if (opts->dregs[reg] >= 0) { + mov_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D); + } else { + mov_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_D); + } +} + +void areg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg) +{ + if (opts->aregs[reg] >= 0) { + movsx_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_W, SZ_D); + } else { + movsx_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_W, SZ_D); + } +} + +void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg) +{ + if (opts->dregs[reg] >= 0) { + movsx_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_W, SZ_D); + } else { + movsx_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_W, SZ_D); + } +} + +void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg) +{ + if (opts->aregs[reg] >= 0) { + mov_rr(&opts->gen.code, native_reg, opts->aregs[reg], SZ_D); + } else { + mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, areg_offset(reg), SZ_D); + } +} + +void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg) +{ + if (opts->dregs[reg] >= 0) { + mov_rr(&opts->gen.code, native_reg, opts->dregs[reg], SZ_D); + } else { + mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, dreg_offset(reg), SZ_D); + } +} + +void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg) +{ + if (opts->aregs[reg] >= 0) { + mov_ir(&opts->gen.code, value, opts->aregs[reg], SZ_D); + } else { + mov_irdisp(&opts->gen.code, value, opts->gen.context_reg, areg_offset(reg), SZ_D); + } +} + +void ldi_native(m68k_options *opts, int32_t value, uint8_t reg) +{ + mov_ir(&opts->gen.code, value, reg, SZ_D); +} + +void addi_areg(m68k_options *opts, int32_t val, uint8_t reg) +{ + if (opts->aregs[reg] >= 0) { + add_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D); + } else { + add_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D); + } +} + +void subi_areg(m68k_options *opts, int32_t val, uint8_t reg) +{ + if (opts->aregs[reg] >= 0) { + sub_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D); + } else { + sub_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D); + } +} + +void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) +{ + if (opts->aregs[reg] >= 0) { + add_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D); + } else { + add_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_D); + } +} + +void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) +{ + if (opts->dregs[reg] >= 0) { + add_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D); + } else { + add_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_D); + } +} + +void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) +{ + areg_to_native(opts, op->params.regs.pri, native_reg); + add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D); +} + +void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) +{ + uint8_t sec_reg = (op->params.regs.sec >> 1) & 0x7; + if (op->params.regs.sec & 1) { + if (op->params.regs.sec & 0x10) { + add_areg_native(opts, sec_reg, native_reg); + } else { + add_dreg_native(opts, sec_reg, native_reg); + } + } else { + uint8_t other_reg = native_reg == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1; + if (op->params.regs.sec & 0x10) { + areg_to_native_sx(opts, sec_reg, other_reg); + } else { + dreg_to_native_sx(opts, sec_reg, other_reg); + } + add_rr(&opts->gen.code, other_reg, native_reg, SZ_D); + } + if (op->params.regs.displacement) { + add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D); + } +} + +void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) +{ + areg_to_native(opts, op->params.regs.pri, native_reg); + calc_index_disp8(opts, op, native_reg); +} + void translate_m68k_op(m68kinst * inst, x86_ea * ea, m68k_options * opts, uint8_t dst) { code_info *code = &opts->gen.code; @@ -230,18 +357,10 @@ if (!dst) { cycles(&opts->gen, PREDEC_PENALTY); } - if (opts->aregs[op->params.regs.pri] >= 0) { - sub_ir(code, dec_amount, opts->aregs[op->params.regs.pri], SZ_D); - } else { - sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(op), SZ_D); - } + subi_areg(opts, dec_amount, op->params.regs.pri); case MODE_AREG_INDIRECT: case MODE_AREG_POSTINC: - if (opts->aregs[op->params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_D); - } + areg_to_native(opts, op->params.regs.pri, opts->gen.scratch1); m68k_read_size(opts, inst->extra.size); if (dst) { @@ -250,33 +369,20 @@ pop_r(code, opts->gen.scratch2); } else { //save reg value in opts->gen.scratch2 so we can use it to save the result in memory later - if (opts->aregs[op->params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch2, SZ_D); - } + areg_to_native(opts, op->params.regs.pri, opts->gen.scratch2); } } if (op->addr_mode == MODE_AREG_POSTINC) { inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 : 1)); - if (opts->aregs[op->params.regs.pri] >= 0) { - add_ir(code, inc_amount, opts->aregs[op->params.regs.pri], SZ_D); - } else { - add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(op), SZ_D); - } + addi_areg(opts, inc_amount, op->params.regs.pri); } ea->mode = MODE_REG_DIRECT; ea->base = (!dst && inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? opts->gen.scratch2 : opts->gen.scratch1; break; case MODE_AREG_DISPLACE: cycles(&opts->gen, BUS); - if (opts->aregs[op->params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_D); - } - add_ir(code, op->params.regs.displacement, opts->gen.scratch1, SZ_D); + calc_areg_displace(opts, op, opts->gen.scratch1); if (dst) { push_r(code, opts->gen.scratch1); } @@ -290,45 +396,7 @@ break; case MODE_AREG_INDEX_DISP8: cycles(&opts->gen, 6); - if (opts->aregs[op->params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[op->params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_D); - } - sec_reg = (op->params.regs.sec >> 1) & 0x7; - if (op->params.regs.sec & 1) { - if (op->params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (op->params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (op->params.regs.displacement) { - add_ir(code, op->params.regs.displacement, opts->gen.scratch1, SZ_D); - } + calc_areg_index_disp8(opts, op, opts->gen.scratch1); if (dst) { push_r(code, opts->gen.scratch1); } @@ -357,40 +425,7 @@ case MODE_PC_INDEX_DISP8: cycles(&opts->gen, 6); mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); - sec_reg = (op->params.regs.sec >> 1) & 0x7; - if (op->params.regs.sec & 1) { - if (op->params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (op->params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (op->params.regs.displacement) { - add_ir(code, op->params.regs.displacement, opts->gen.scratch1, SZ_D); - } + calc_index_disp8(opts, op, opts->gen.scratch1); if (dst) { push_r(code, opts->gen.scratch1); } @@ -450,11 +485,7 @@ code_info *code = &opts->gen.code; if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) { - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } + areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2); } switch (inst->extra.size) { @@ -531,18 +562,10 @@ break; case MODE_AREG_PREDEC: dec_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) { - sub_ir(code, dec_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); - } else { - sub_irdisp(code, dec_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } + subi_areg(opts, dec_amount, inst->dst.params.regs.pri); case MODE_AREG_INDIRECT: case MODE_AREG_POSTINC: - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } + areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2); if (src.mode == MODE_REG_DIRECT) { if (src.base != opts->gen.scratch1) { mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); @@ -561,21 +584,12 @@ 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) { - add_ir(code, inc_amount, opts->aregs[inst->dst.params.regs.pri], SZ_D); - } else { - add_irdisp(code, inc_amount, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } + addi_areg(opts, inc_amount, inst->dst.params.regs.pri); } break; case MODE_AREG_DISPLACE: cycles(&opts->gen, BUS); - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); + calc_areg_displace(opts, &inst->dst, opts->gen.scratch2); if (src.mode == MODE_REG_DIRECT) { if (src.base != opts->gen.scratch1) { mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size); @@ -594,50 +608,13 @@ break; case MODE_AREG_INDEX_DISP8: cycles(&opts->gen, 6);//TODO: Check to make sure this is correct - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); + //calc_areg_index_disp8 will clober scratch1 when a 16-bit index is used + if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { + push_r(code, opts->gen.scratch1); } - sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; - if (inst->dst.params.regs.sec & 1) { - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } - } else { - if (src.base == opts->gen.scratch1) { - push_r(code, opts->gen.scratch1); - } - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); - if (src.base == opts->gen.scratch1) { - pop_r(code, opts->gen.scratch1); - } - } - if (inst->dst.params.regs.displacement) { - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); + calc_areg_index_disp8(opts, &inst->dst, opts->gen.scratch2); + if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { + pop_r(code, opts->gen.scratch1); } if (src.mode == MODE_REG_DIRECT) { if (src.base != opts->gen.scratch1) { @@ -677,45 +654,12 @@ case MODE_PC_INDEX_DISP8: cycles(&opts->gen, 6);//TODO: Check to make sure this is correct mov_ir(code, inst->address, opts->gen.scratch2, SZ_D); - sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; - if (inst->dst.params.regs.sec & 1) { - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } - } else { - if (src.base == opts->gen.scratch1) { - push_r(code, opts->gen.scratch1); - } - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); - if (src.base == opts->gen.scratch1) { - pop_r(code, opts->gen.scratch1); - } + if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { + push_r(code, opts->gen.scratch1); } - if (inst->dst.params.regs.displacement) { - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); + calc_index_disp8(opts, &inst->dst, opts->gen.scratch2); + if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { + pop_r(code, opts->gen.scratch1); } if (src.mode == MODE_REG_DIRECT) { if (src.base != opts->gen.scratch1) { @@ -780,63 +724,15 @@ { case MODE_AREG_INDIRECT: case MODE_AREG_PREDEC: - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } + areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2); break; case MODE_AREG_DISPLACE: early_cycles += BUS; - reg = opts->gen.scratch2; - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); + calc_areg_displace(opts, &inst->dst, opts->gen.scratch2); break; case MODE_AREG_INDEX_DISP8: early_cycles += 6; - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } - sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; - if (inst->dst.params.regs.sec & 1) { - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } - } else { - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); - } - if (inst->dst.params.regs.displacement) { - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); - } + calc_areg_index_disp8(opts, &inst->dst, opts->gen.scratch2); break; case MODE_PC_DISPLACE: early_cycles += BUS; @@ -845,41 +741,7 @@ case MODE_PC_INDEX_DISP8: early_cycles += 6; mov_ir(code, inst->address+2, opts->gen.scratch2, SZ_D); - sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7; - if (inst->dst.params.regs.sec & 1) { - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } - } else { - if (inst->dst.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); - } - if (inst->dst.params.regs.displacement) { - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); - } - break; + calc_index_disp8(opts, &inst->dst, opts->gen.scratch2); case MODE_ABSOLUTE: early_cycles += 4; case MODE_ABSOLUTE_SHORT: @@ -906,17 +768,9 @@ } push_r(code, opts->gen.scratch2); if (reg > 7) { - if (opts->aregs[reg-8] >= 0) { - mov_rr(code, opts->aregs[reg-8], opts->gen.scratch1, inst->extra.size); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), opts->gen.scratch1, inst->extra.size); - } + areg_to_native(opts, reg-8, opts->gen.scratch1); } else { - if (opts->dregs[reg] >= 0) { - mov_rr(code, opts->dregs[reg], opts->gen.scratch1, inst->extra.size); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), opts->gen.scratch1, inst->extra.size); - } + dreg_to_native(opts, reg, opts->gen.scratch1); } if (inst->extra.size == OPSIZE_LONG) { call(code, opts->write_32_lowfirst); @@ -930,11 +784,7 @@ } } if (inst->dst.addr_mode == MODE_AREG_PREDEC) { - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->gen.scratch2, opts->aregs[inst->dst.params.regs.pri], SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } + native_to_areg(opts, opts->gen.scratch2, inst->dst.params.regs.pri); } } else { //mem to reg @@ -943,63 +793,16 @@ { case MODE_AREG_INDIRECT: case MODE_AREG_POSTINC: - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } + areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1); break; case MODE_AREG_DISPLACE: early_cycles += BUS; reg = opts->gen.scratch2; - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); + calc_areg_displace(opts, &inst->src, opts->gen.scratch1); break; case MODE_AREG_INDEX_DISP8: early_cycles += 6; - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } + calc_areg_index_disp8(opts, &inst->src, opts->gen.scratch1); break; case MODE_PC_DISPLACE: early_cycles += BUS; @@ -1008,40 +811,7 @@ case MODE_PC_INDEX_DISP8: early_cycles += 6; mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } + calc_index_disp8(opts, &inst->src, opts->gen.scratch1); break; case MODE_ABSOLUTE: early_cycles += 4; @@ -1067,28 +837,16 @@ movsx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W, SZ_D); } if (reg > 7) { - if (opts->aregs[reg-8] >= 0) { - mov_rr(code, opts->gen.scratch1, opts->aregs[reg-8], SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * (reg-8), SZ_D); - } + native_to_areg(opts, opts->gen.scratch1, reg-8); } else { - if (opts->dregs[reg] >= 0) { - mov_rr(code, opts->gen.scratch1, opts->dregs[reg], SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * (reg), SZ_D); - } + native_to_dreg(opts, opts->gen.scratch1, reg); } pop_r(code, opts->gen.scratch1); add_ir(code, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch1, SZ_D); } } if (inst->src.addr_mode == MODE_AREG_POSTINC) { - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->gen.scratch1, opts->aregs[inst->src.params.regs.pri], SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); - } + native_to_areg(opts, opts->gen.scratch1, inst->src.params.regs.pri); } } //prefetch @@ -1141,270 +899,6 @@ //M68K EXT only operates on registers so no need for a call to save result here } -void translate_m68k_lea(m68k_options * opts, m68kinst * inst) -{ - code_info *code = &opts->gen.code; - int8_t dst_reg = native_reg(&(inst->dst), opts), sec_reg; - switch(inst->src.addr_mode) - { - case MODE_AREG_INDIRECT: - cycles(&opts->gen, BUS); - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - if (dst_reg >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); - } else { - mov_rrdisp(code, opts->aregs[inst->src.params.regs.pri], opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); - } - } else { - if (dst_reg >= 0) { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, dst_reg, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); - } - } - break; - case MODE_AREG_DISPLACE: - cycles(&opts->gen, 8); - if (dst_reg >= 0) { - if (inst->src.params.regs.pri != inst->dst.params.regs.pri) { - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], dst_reg, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), dst_reg, SZ_D); - } - } - add_ir(code, inst->src.params.regs.displacement, dst_reg, SZ_D); - } else { - if (inst->src.params.regs.pri != inst->dst.params.regs.pri) { - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rrdisp(code, opts->aregs[inst->src.params.regs.pri], opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } - } - add_irdisp(code, inst->src.params.regs.displacement, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } - break; - case MODE_AREG_INDEX_DISP8: - cycles(&opts->gen, 12); - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch2, SZ_D); - } - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_D); - } - } - } else { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch2, SZ_D); - } - if (dst_reg >= 0) { - mov_rr(code, opts->gen.scratch2, dst_reg, SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } - break; - case MODE_PC_DISPLACE: - cycles(&opts->gen, 8); - if (dst_reg >= 0) { - mov_ir(code, inst->src.params.regs.displacement + inst->address+2, dst_reg, SZ_D); - } else { - mov_irdisp(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->dst.params.regs.pri, SZ_D); - } - break; - case MODE_PC_INDEX_DISP8: - cycles(&opts->gen, BUS*3); - mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } - if (dst_reg >= 0) { - mov_rr(code, opts->gen.scratch1, dst_reg, SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } - break; - case MODE_ABSOLUTE: - case MODE_ABSOLUTE_SHORT: - cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); - if (dst_reg >= 0) { - mov_ir(code, inst->src.params.immed, dst_reg, SZ_D); - } else { - mov_irdisp(code, inst->src.params.immed, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_D); - } - break; - default: - m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); - exit(1); - } -} - -void translate_m68k_pea(m68k_options * opts, m68kinst * inst) -{ - code_info *code = &opts->gen.code; - uint8_t sec_reg; - switch(inst->src.addr_mode) - { - case MODE_AREG_INDIRECT: - cycles(&opts->gen, BUS); - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); - } - break; - case MODE_AREG_DISPLACE: - cycles(&opts->gen, 8); - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - break; - case MODE_AREG_INDEX_DISP8: - cycles(&opts->gen, 6);//TODO: Check to make sure this is correct - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } - break; - case MODE_PC_DISPLACE: - cycles(&opts->gen, 8); - mov_ir(code, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); - break; - case MODE_ABSOLUTE: - case MODE_ABSOLUTE_SHORT: - cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2); - mov_ir(code, inst->src.params.immed, opts->gen.scratch1, SZ_D); - break; - default: - m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); - exit(1); - } - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_lowfirst); -} - -void translate_m68k_bsr(m68k_options * opts, m68kinst * inst) -{ - code_info *code = &opts->gen.code; - int32_t disp = inst->src.params.immed; - uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : 4); - //TODO: Add cycles in the right place relative to pushing the return address on the stack - cycles(&opts->gen, 10); - mov_ir(code, after, opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - code_ptr dest_addr = get_native_address(opts->gen.native_code_map, (inst->address+2) + disp); - if (!dest_addr) { - opts->gen.deferred = defer_address(opts->gen.deferred, (inst->address+2) + disp, code->cur + 1); - //dummy address to be replaced later - dest_addr = code->cur + 256; - } - jmp(code, dest_addr); -} - uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) { uint8_t cond = CC_NZ; @@ -1458,15 +952,10 @@ cycles(&opts->gen, 10);//TODO: Adjust this for branch not taken case int32_t disp = inst->src.params.immed; uint32_t after = inst->address + 2; - code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + disp); if (inst->extra.cond == COND_TRUE) { - if (!dest_addr) { - opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, code->cur + 1); - //dummy address to be replaced later, make sure it generates a 4-byte displacement - dest_addr = code->cur + 256; - } - jmp(code, dest_addr); + jump_m68k_abs(opts, after + disp); } else { + code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + disp); uint8_t cond = m68k_eval_cond(opts, inst->extra.cond); if (!dest_addr) { opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, code->cur + 2); @@ -1520,214 +1009,6 @@ m68k_save_result(inst, opts); } -void translate_m68k_jmp_jsr(m68k_options * opts, m68kinst * inst) -{ - uint8_t is_jsr = inst->op == M68K_JSR; - code_info *code = &opts->gen.code; - code_ptr dest_addr; - uint8_t sec_reg; - uint32_t after; - uint32_t m68k_addr; - switch(inst->src.addr_mode) - { - case MODE_AREG_INDIRECT: - cycles(&opts->gen, BUS*2); - if (is_jsr) { - mov_ir(code, inst->address + 2, opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - } - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); - } - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); - break; - case MODE_AREG_DISPLACE: - cycles(&opts->gen, BUS*2); - if (is_jsr) { - mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - } - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, opts->gen.scratch1, SZ_D); - } - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); - break; - case MODE_AREG_INDEX_DISP8: - cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct - if (is_jsr) { - mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - } - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - //32-bit index register - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - //16-bit index register - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); - break; - case MODE_PC_DISPLACE: - //TODO: Add cycles in the right place relative to pushing the return address on the stack - cycles(&opts->gen, 10); - if (is_jsr) { - mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - } - m68k_addr = inst->src.params.regs.displacement + inst->address + 2; - if ((m68k_addr & 0xFFFFFF) < 0x400000) { - dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); - if (!dest_addr) { - opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, code->cur + 1); - //dummy address to be replaced later, make sure it generates a 4-byte displacement - dest_addr = code->cur + 256; - } - jmp(code, dest_addr); - } else { - mov_ir(code, m68k_addr, opts->gen.scratch1, SZ_D); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); - } - break; - case MODE_PC_INDEX_DISP8: - cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct - if (is_jsr) { - mov_ir(code, inst->address + 4, opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - } - mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); - sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; - if (inst->src.params.regs.sec & 1) { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - add_rr(code, opts->aregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - add_rr(code, opts->dregs[sec_reg], opts->gen.scratch1, SZ_D); - } else { - add_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch1, SZ_D); - } - } - } else { - if (inst->src.params.regs.sec & 0x10) { - if (opts->aregs[sec_reg] >= 0) { - movsx_rr(code, opts->aregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } else { - if (opts->dregs[sec_reg] >= 0) { - movsx_rr(code, opts->dregs[sec_reg], opts->gen.scratch2, SZ_W, SZ_D); - } else { - movsx_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, opts->gen.scratch2, SZ_W, SZ_D); - } - } - add_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); - break; - case MODE_ABSOLUTE: - case MODE_ABSOLUTE_SHORT: - //TODO: Add cycles in the right place relative to pushing the return address on the stack - cycles(&opts->gen, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); - if (is_jsr) { - mov_ir(code, inst->address + (inst->src.addr_mode == MODE_ABSOLUTE ? 6 : 4), opts->gen.scratch1, SZ_D); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - call(code, opts->write_32_highfirst); - } - m68k_addr = inst->src.params.immed; - if ((m68k_addr & 0xFFFFFF) < 0x400000) { - dest_addr = get_native_address(opts->gen.native_code_map, m68k_addr); - if (!dest_addr) { - opts->gen.deferred = defer_address(opts->gen.deferred, m68k_addr, code->cur + 1); - //dummy address to be replaced later, make sure it generates a 4-byte displacement - dest_addr = code->cur + 256; - } - jmp(code, dest_addr); - } else { - mov_ir(code, m68k_addr, opts->gen.scratch1, SZ_D); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); - } - break; - default: - m68k_disasm(inst, disasm_buf); - printf("%s\naddress mode %d not yet supported (%s)\n", disasm_buf, inst->src.addr_mode, is_jsr ? "jsr" : "jmp"); - exit(1); - } -} - -void translate_m68k_rts(m68k_options * opts, m68kinst * inst) -{ - code_info *code = &opts->gen.code; - //TODO: Add cycles - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); - add_ir(code, 4, opts->aregs[7], SZ_D); - call(code, opts->read_32); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); -} - void translate_m68k_dbcc(m68k_options * opts, m68kinst * inst) { code_info *code = &opts->gen.code; @@ -1752,13 +1033,7 @@ code_ptr loop_end_loc = code->cur + 1; jcc(code, CC_Z, code->cur + 2); uint32_t after = inst->address + 2; - code_ptr dest_addr = get_native_address(opts->gen.native_code_map, after + inst->src.params.immed); - if (!dest_addr) { - opts->gen.deferred = defer_address(opts->gen.deferred, after + inst->src.params.immed, code->cur + 1); - //dummy address to be replaced later, make sure it generates a 4-byte displacement - dest_addr = code->cur + 256; - } - jmp(code, dest_addr); + jump_m68k_abs(opts, after + inst->src.params.immed); *loop_end_loc = code->cur - (loop_end_loc+1); if (skip_loc) { cycles(&opts->gen, 2); @@ -1769,44 +1044,13 @@ } } -void translate_m68k_link(m68k_options * opts, m68kinst * inst) -{ - code_info *code = &opts->gen.code; - int8_t reg = native_reg(&(inst->src), opts); - //compensate for displacement word - cycles(&opts->gen, BUS); - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - if (reg >= 0) { - mov_rr(code, reg, opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - call(code, opts->write_32_highfirst); - if (reg >= 0) { - mov_rr(code, opts->aregs[7], reg, SZ_D); - } else { - mov_rrdisp(code, opts->aregs[7], opts->gen.context_reg, reg_offset(&(inst->src)), SZ_D); - } - add_ir(code, inst->dst.params.immed, opts->aregs[7], SZ_D); - //prefetch - cycles(&opts->gen, BUS); -} - void translate_m68k_movep(m68k_options * opts, m68kinst * inst) { code_info *code = &opts->gen.code; int8_t reg; cycles(&opts->gen, BUS*2); if (inst->src.addr_mode == MODE_REG) { - if (opts->aregs[inst->dst.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->dst.params.regs.pri], opts->gen.scratch2, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->dst)), opts->gen.scratch2, SZ_D); - } - if (inst->dst.params.regs.displacement) { - add_ir(code, inst->dst.params.regs.displacement, opts->gen.scratch2, SZ_D); - } + calc_areg_displace(opts, &inst->dst, opts->gen.scratch2); reg = native_reg(&(inst->src), opts); if (inst->extra.size == OPSIZE_LONG) { if (reg >= 0) { @@ -1848,14 +1092,7 @@ add_ir(code, 2, opts->gen.scratch2, SZ_D); call(code, opts->write_8); } else { - if (opts->aregs[inst->src.params.regs.pri] >= 0) { - mov_rr(code, opts->aregs[inst->src.params.regs.pri], opts->gen.scratch1, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_D); - } - if (inst->src.params.regs.displacement) { - add_ir(code, inst->src.params.regs.displacement, opts->gen.scratch1, SZ_D); - } + calc_areg_displace(opts, &inst->src, opts->gen.scratch1); reg = native_reg(&(inst->dst), opts); if (inst->extra.size == OPSIZE_LONG) { if (reg >= 0) { @@ -2144,6 +1381,8 @@ return translate_m68k_movem(opts, inst); } else if(inst->op == M68K_LINK) { return translate_m68k_link(opts, inst); + } else if(inst->op == M68K_UNLK) { + return translate_m68k_unlk(opts, inst); } else if(inst->op == M68K_EXT) { return translate_m68k_ext(opts, inst); } else if(inst->op == M68K_SCC) { @@ -2723,19 +1962,16 @@ //TODO: Trap if not in supervisor mode //bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); if (inst->src.addr_mode == MODE_UNUSED) { - if (dst_op.mode == MODE_REG_DIRECT) { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, dst_op.base, SZ_D); - } else { - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->gen.scratch1, SZ_D); + areg_to_native(opts, 8, dst_op.mode == MODE_REG_DIRECT ? dst_op.base : opts->gen.scratch1); + if (dst_op.mode != MODE_REG_DIRECT) { mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D); } } else { - if (src_op.mode == MODE_REG_DIRECT) { - mov_rrdisp(code, src_op.base, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); - } else { + if (src_op.mode != MODE_REG_DIRECT) { mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D); - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); + src_op.base = opts->gen.scratch1; } + native_to_areg(opts, src_op.base, 8); } break; //case M68K_MOVEP: @@ -3133,39 +2369,26 @@ case M68K_RTE: //TODO: Trap if not in system mode //Read saved SR - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); + areg_to_native(opts, 7, opts->gen.scratch1); call(code, opts->read_16); - add_ir(code, 2, opts->aregs[7], SZ_D); + addi_areg(opts, 2, 7); call(code, opts->set_sr); //Read saved PC - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); + areg_to_native(opts, 7, opts->gen.scratch1); call(code, opts->read_32); - add_ir(code, 4, opts->aregs[7], SZ_D); + addi_areg(opts, 4, 7); //Check if we've switched to user mode and swap stack pointers if needed bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); end_off = code->cur + 1; jcc(code, CC_C, code->cur + 2); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); - mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); + swap_ssp_usp(opts); *end_off = code->cur - (end_off+1); //Get native address, sync components, recalculate integer points and jump to returned address call(code, opts->native_addr_and_sync); jmp_r(code, opts->gen.scratch1); break; case M68K_RTR: - //Read saved CCR - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); - call(code, opts->read_16); - add_ir(code, 2, opts->aregs[7], SZ_D); - call(code, opts->set_ccr); - //Read saved PC - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); - call(code, opts->read_32); - add_ir(code, 4, opts->aregs[7], SZ_D); - //Get native address and jump to it - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + translate_m68k_rtr(opts, inst); break; case M68K_SBCD: { if (src_op.base != opts->gen.scratch2) { @@ -3216,9 +2439,7 @@ mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { //leave supervisor mode - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); - mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); + swap_ssp_usp(opts); } code_ptr loop_top = code->cur; call(code, opts->do_sync); @@ -3317,9 +2538,7 @@ break; //case M68K_TAS: case M68K_TRAP: - mov_ir(code, src_op.disp + VECTOR_TRAP_0, opts->gen.scratch2, SZ_D); - mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); - jmp(code, opts->trap); + translate_m68k_trap(opts, inst); break; //case M68K_TRAPV: case M68K_TST: @@ -3334,22 +2553,6 @@ set_flag_cond(opts, CC_S, FLAG_N); set_flag(opts, 0, FLAG_V); break; - case M68K_UNLK: - cycles(&opts->gen, BUS); - if (dst_op.mode == MODE_REG_DIRECT) { - mov_rr(code, dst_op.base, opts->aregs[7], SZ_D); - } else { - mov_rdispr(code, dst_op.base, dst_op.disp, opts->aregs[7], SZ_D); - } - mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); - call(code, opts->read_32); - if (dst_op.mode == MODE_REG_DIRECT) { - mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_D); - } else { - mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D); - } - add_ir(code, 4, opts->aregs[7], SZ_D); - break; default: m68k_disasm(inst, disasm_buf); printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); @@ -4141,18 +3344,16 @@ bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); code_ptr already_supervisor = code->cur + 1; jcc(code, CC_C, code->cur + 2); - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->gen.scratch2, SZ_D); - mov_rrdisp(code, opts->aregs[7], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); - mov_rr(code, opts->gen.scratch2, opts->aregs[7], SZ_D); + swap_ssp_usp(opts); *already_supervisor = code->cur - (already_supervisor+1); //save PC - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); call(code, opts->write_32_lowfirst); //save status register - sub_ir(code, 2, opts->aregs[7], SZ_D); + subi_areg(opts, 2, 7); call(code, opts->get_sr); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); + areg_to_native(opts, 7, opts->gen.scratch2); call(code, opts->write_16); //update status register and_irdisp(code, 0xF8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); @@ -4177,18 +3378,16 @@ bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); already_supervisor = code->cur + 1; jcc(code, CC_C, code->cur + 2); - mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->gen.scratch2, SZ_D); - mov_rrdisp(code, opts->aregs[7], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); - mov_rr(code, opts->gen.scratch2, opts->aregs[7], SZ_D); + swap_ssp_usp(opts); *already_supervisor = code->cur - (already_supervisor+1); //save PC - sub_ir(code, 4, opts->aregs[7], SZ_D); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); call(code, opts->write_32_lowfirst); //save status register - sub_ir(code, 2, opts->aregs[7], SZ_D); + subi_areg(opts, 2, 7); call(code, opts->get_sr); - mov_rr(code, opts->aregs[7], opts->gen.scratch2, SZ_D); + areg_to_native(opts, 7, opts->gen.scratch2); call(code, opts->write_16); //set supervisor bit or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); @@ -4200,13 +3399,3 @@ cycles(&opts->gen, 18); jmp_r(code, opts->gen.scratch1); } - -void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) -{ - memset(context, 0, sizeof(m68k_context)); - context->native_code_map = native_code_map; - context->options = opts; - context->int_cycle = 0xFFFFFFFF; - context->status = 0x27; -} - diff -r 29d99db6f55d -r 1594525e2157 m68k_internal.h --- a/m68k_internal.h Mon Mar 03 22:16:41 2014 -0800 +++ b/m68k_internal.h Mon Mar 03 22:17:20 2014 -0800 @@ -11,13 +11,33 @@ //functions implemented in host CPU specfic file void translate_out_of_bounds(code_info *code); void check_code_prologue(code_info *code); +void areg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg); +void dreg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg); +void areg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg); +void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg); +void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg); +void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg); +void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg); +void ldi_native(m68k_options *opts, int32_t value, uint8_t reg); +void addi_areg(m68k_options *opts, int32_t val, uint8_t reg); +void subi_areg(m68k_options *opts, int32_t val, uint8_t reg); +void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg); +void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg); +void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg); +void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg); +void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg); //functions implemented in m68k_core.c int8_t native_reg(m68k_op_info * op, m68k_options * opts); +size_t dreg_offset(uint8_t reg); +size_t areg_offset(uint8_t reg); size_t reg_offset(m68k_op_info *op); void print_regs_exit(m68k_context * context); void m68k_read_size(m68k_options *opts, uint8_t size); void m68k_write_size(m68k_options *opts, uint8_t size); +void push_const(m68k_options *opts, int32_t value); +void jump_m68k_abs(m68k_options * opts, uint32_t address); +void swap_ssp_usp(m68k_options * opts); code_ptr get_native_address(native_map_slot * native_code_map, uint32_t address); void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size); uint8_t get_native_inst_size(m68k_options * opts, uint32_t address); @@ -25,4 +45,25 @@ void m68k_handle_deferred(m68k_context * context); code_ptr get_native_address_trans(m68k_context * context, uint32_t address); +//individual instructions +void translate_m68k_lea(m68k_options * opts, m68kinst * inst); +void translate_m68k_pea(m68k_options * opts, m68kinst * inst); +void translate_m68k_bsr(m68k_options * opts, m68kinst * inst); +void translate_m68k_jmp_jsr(m68k_options * opts, m68kinst * inst); +void translate_m68k_unlk(m68k_options * opts, m68kinst * inst); +void translate_m68k_link(m68k_options * opts, m68kinst * inst); +void translate_m68k_rts(m68k_options * opts, m68kinst * inst); +void translate_m68k_rtr(m68k_options *opts, m68kinst * inst); +void translate_m68k_trap(m68k_options *opts, m68kinst *inst); + +#define BUS 4 +#define PREDEC_PENALTY 2 +extern char disasm_buf[1024]; + +m68k_context * sync_components(m68k_context * context, uint32_t address); + +void m68k_invalid(); +void bcd_add(); +void bcd_sub(); + #endif //M68K_INTERNAL_H_