# HG changeset patch # User Mike Pavone # Date 1354037293 28800 # Node ID 2bdad0f52f42f7f8937255e7878be317b07d533d # Parent 168b1a873895e614a2bb2d491a1bd2dde287eaa1 x86 code gen, initial work on translator diff -r 168b1a873895 -r 2bdad0f52f42 68kinst.h --- a/68kinst.h Thu Nov 15 22:15:43 2012 -0800 +++ b/68kinst.h Tue Nov 27 09:28:13 2012 -0800 @@ -1,3 +1,6 @@ +#ifndef M68KINST_H_ +#define M68KINST_H_ + #include typedef enum { @@ -176,3 +179,5 @@ uint32_t m68k_cycles(m68kinst * inst); int m68K_disasm(m68kinst * decoded, char * dst); +#endif + diff -r 168b1a873895 -r 2bdad0f52f42 gen_x86.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen_x86.c Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,512 @@ +#include "gen_x86.h" +#include "68kinst.h" +#include +#include + +#define REX_RM_FIELD 0x1 +#define REX_SIB_FIELD 0x2 +#define REX_REG_FIELD 0x4 +#define REX_QUAD 0x8 + +#define OP_ADD 0x00 +#define OP_OR 0x08 +#define PRE_2BYTE 0x0F +#define OP_ADC 0x10 +#define OP_SBB 0x18 +#define OP_AND 0x20 +#define OP_SUB 0x28 +#define OP_XOR 0x30 +#define OP_CMP 0x38 +#define PRE_REX 0x40 +#define OP_PUSH 0x50 +#define OP_POP 0x58 +#define PRE_SIZE 0x66 +#define OP_JCC 0x70 +#define OP_IMMED_ARITH 0x80 +#define OP_MOV 0x88 +#define OP_PUSHF 0x9C +#define OP_POPF 0x9D +#define OP_MOV_I8R 0xB0 +#define OP_MOV_IR 0xB8 +#define OP_RETN 0xC3 +#define OP_CALL 0xE8 +#define OP_CALL_EA 0xFF + +#define OP2_JCC 0x80 +#define OP2_SETCC 0x90 + +#define OP_EX_ADDI 0x0 +#define OP_EX_ORI 0x1 +#define OP_EX_ADCI 0x2 +#define OP_EX_SBBI 0x3 +#define OP_EX_ANDI 0x4 +#define OP_EX_SUBI 0x5 +#define OP_EX_XORI 0x6 +#define OP_EX_CMPI 0x7 + +#define BIT_IMMED_RAX 0x4 +#define BIT_DIR 0x2 +#define BIT_SIZE 0x1 + +#define M68K_N_REG RBX +#define M68K_V_REG BH +#define M68K_Z_REG RDX +#define M68K_C_REG DH + +#define M68K_SCRATCH RCX + +enum { + X86_RAX = 0, + X86_RCX, + X86_RDX, + X86_RBX, + X86_RSP, + X86_RBP, + X86_RSI, + X86_RDI, + X86_AH=4, + X86_CH, + X86_DH, + X86_BH, + X86_R8=0, + X86_R9, + X86_R10, + X86_R11, + X86_R12, + X86_R13, + X86_R14, + X86_R15 +} x86_regs_enc; + +enum { + MODE_REG_INDIRECT = 0, + MODE_REG_DISPLACE8 = 0x40, + MODE_REG_DIPSLACE32 = 0x80, + MODE_REG_DIRECT = 0xC0 +} x86_modes; + +uint8_t * x86_rr_sizedir(uint8_t * out, uint8_t opcode, uint8_t src, uint8_t dst, uint8_t size) +{ + //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix + uint8_t tmp; + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (size == SZ_B && dst >= RSP && dst <= RDI) { + opcode |= BIT_DIR; + tmp = dst; + dst = src; + src = dst; + } + if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { + *out = PRE_REX; + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (src >= R8) { + *out |= REX_REG_FIELD; + src -= (R8 - X86_R8); + } + if (dst >= R8) { + *out |= REX_RM_FIELD; + dst -= (R8 - X86_R8); + } + out++; + } + if (size == SZ_B) { + if (src >= AH && src <= BH) { + src -= (AH-X86_AH); + } + if (dst >= AH && dst <= BH) { + dst -= (AH-X86_AH); + } + } else { + opcode |= BIT_SIZE; + } + *(out++) = opcode; + *(out++) = MODE_REG_DIRECT | dst | (src << 3); + return out; +} + +uint8_t * x86_rrdisp8_sizedir(uint8_t * out, uint8_t opcode, uint8_t reg, uint8_t base, int8_t disp, uint8_t size, uint8_t dir) +{ + //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix + uint8_t tmp; + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { + *out = PRE_REX; + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (reg >= R8) { + *out |= REX_REG_FIELD; + reg -= (R8 - X86_R8); + } + if (base >= R8) { + *out |= REX_RM_FIELD; + base -= (R8 - X86_R8); + } + out++; + } + if (size == SZ_B) { + if (reg >= AH && reg <= BH) { + reg -= (AH-X86_AH); + } + } else { + opcode |= BIT_SIZE; + } + *(out++) = opcode | dir; + *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3); + *(out++) = disp; + return out; +} + +uint8_t * x86_rrind_sizedir(uint8_t * out, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t size, uint8_t dir) +{ + //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix + uint8_t tmp; + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { + *out = PRE_REX; + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (reg >= R8) { + *out |= REX_REG_FIELD; + reg -= (R8 - X86_R8); + } + if (base >= R8) { + *out |= REX_RM_FIELD; + base -= (R8 - X86_R8); + } + out++; + } + if (size == SZ_B) { + if (reg >= AH && reg <= BH) { + reg -= (AH-X86_AH); + } + } else { + opcode |= BIT_SIZE; + } + *(out++) = opcode | dir; + *(out++) = MODE_REG_INDIRECT | base | (reg << 3); + return out; +} + +uint8_t * x86_i8r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, uint8_t val, uint8_t dst) +{ + if (dst == RAX) { + *(out++) = al_opcode | BIT_IMMED_RAX; + } else { + if (dst >= AH && dst <= BH) { + dst -= (AH-X86_AH); + } else if(dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + } + *(out++) = opcode; + *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); + } + *(out++) = val; + return out; +} + +uint8_t * x86_i32r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst) +{ + uint8_t sign_extend = 0; + if (val <= 0x7F && val >= -0x80) { + sign_extend = 1; + opcode |= BIT_DIR; + } + if (dst == RAX && !sign_extend) { + *(out++) = al_opcode | BIT_IMMED_RAX | BIT_SIZE; + } else { + if(dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + } + *(out++) = opcode | BIT_SIZE; + *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); + } + *(out++) = val; + if (!sign_extend) { + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + } + return out; +} + +uint8_t * add_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_ADD, src, dst, size); +} + +uint8_t * add_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst); +} + +uint8_t * add_i32r(uint8_t * out, int32_t val, uint8_t dst) +{ + return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst); +} + +uint8_t * or_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_OR, src, dst, size); +} + +uint8_t * or_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst); +} + +uint8_t * or_i32r(uint8_t * out, int32_t val, uint8_t dst) +{ + return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst); +} + +uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_AND, src, dst, size); +} + +uint8_t * and_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst); +} + +uint8_t * and_i32r(uint8_t * out, int32_t val, uint8_t dst) +{ + return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst); +} + +uint8_t * xor_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_XOR, src, dst, size); +} + +uint8_t * xor_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + return x86_i8r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst); +} + +uint8_t * xor_i32r(uint8_t * out, int32_t val, uint8_t dst) +{ + return x86_i32r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst); +} + +uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_SUB, src, dst, size); +} + +uint8_t * sub_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + return x86_i8r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst); +} + +uint8_t * sub_i32r(uint8_t * out, int32_t val, uint8_t dst) +{ + return x86_i32r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst); +} + + +uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_CMP, src, dst, size); +} + +uint8_t * cmp_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + return x86_i8r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst); +} + +uint8_t * cmp_i32r(uint8_t * out, int32_t val, uint8_t dst) +{ + return x86_i32r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst); +} + +uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rr_sizedir(out, OP_MOV, src, dst, size); +} + +uint8_t * mov_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size) +{ + return x86_rrdisp8_sizedir(out, OP_MOV, src, dst_base, disp, size, 0); +} + +uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size) +{ + return x86_rrdisp8_sizedir(out, OP_MOV, dst, src_base, disp, size, BIT_DIR); +} + +uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rrind_sizedir(out, OP_MOV, src, dst, size, 0); +} + +uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) +{ + return x86_rrind_sizedir(out, OP_MOV, dst, src, size, BIT_DIR); +} + +uint8_t * mov_i8r(uint8_t * out, uint8_t val, uint8_t dst) +{ + if (dst >= AH && dst <= BH) { + dst -= AH - X86_AH; + } else if (dst >= RSP && dst <= RDI) { + *(out++) = PRE_REX; + } else if (dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + dst -= R8 - X86_R8; + } + *(out++) = OP_MOV_I8R | dst; + *(out++) = val; + return out; +} + +uint8_t * mov_i16r(uint8_t * out, uint16_t val, uint8_t dst) +{ + *(out++) = PRE_SIZE; + if (dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + dst -= R8 - X86_R8; + } + *(out++) = OP_MOV_IR | dst; + *(out++) = val; + val >>= 8; + *(out++) = val; + return out; +} + +uint8_t * mov_i32r(uint8_t * out, uint32_t val, uint8_t dst) +{ + if (dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + dst -= R8 - X86_R8; + } + *(out++) = OP_MOV_IR | dst; + *(out++) = val; + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + val >>= 8; + *(out++) = val; + return out; +} + +uint8_t * pushf(uint8_t * out) +{ + *(out++) = OP_PUSHF; + return out; +} + +uint8_t * popf(uint8_t * out) +{ + *(out++) = OP_POPF; + return out; +} + +uint8_t * push_r(uint8_t * out, uint8_t reg) +{ + if (reg >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + reg -= R8 - X86_R8; + } + *(out++) = OP_PUSH | reg; + return out; +} + +uint8_t * pop_r(uint8_t * out, uint8_t reg) +{ + if (reg >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + reg -= R8 - X86_R8; + } + *(out++) = OP_POP | reg; + return out; +} + +uint8_t * setcc_r(uint8_t * out, uint8_t cc, uint8_t dst) +{ + if (dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + dst -= R8 - X86_R8; + } else if (dst >= RSP && dst <= RDI) { + *(out++) = PRE_REX; + } else if (dst >= AH && dst <= BH) { + dst -= AH - X86_AH; + } + *(out++) = PRE_2BYTE; + *(out++) = OP2_SETCC | cc; + *(out++) = MODE_REG_DIRECT | dst; + return out; +} + +uint8_t * setcc_rind(uint8_t * out, uint8_t cc, uint8_t dst) +{ + if (dst >= R8) { + *(out++) = PRE_REX | REX_RM_FIELD; + dst -= R8 - X86_R8; + } + *(out++) = PRE_2BYTE; + *(out++) = OP2_SETCC | cc; + *(out++) = MODE_REG_INDIRECT | dst; + return out; +} + +uint8_t * jcc(uint8_t * out, uint8_t cc, int32_t disp) +{ + if (disp <= 0x7F && disp >= -0x80) { + *(out++) = OP_JCC | cc; + *(out++) = disp; + } else { + *(out++) = PRE_2BYTE; + *(out++) = OP2_JCC | cc; + *(out++) = disp; + disp >>= 8; + *(out++) = disp; + disp >>= 8; + *(out++) = disp; + disp >>= 8; + *(out++) = disp; + } + return out; +} + +uint8_t * call(uint8_t * out, uint8_t * fun) +{ + ptrdiff_t disp = fun-(out+5); + if (disp <= 0x7FFFFFFF && disp >= -2147483648) { + *(out++) = OP_CALL; + *(out++) = disp; + disp >>= 8; + *(out++) = disp; + disp >>= 8; + *(out++) = disp; + disp >>= 8; + *(out++) = disp; + } else { + //TODO: Implement far call + printf("%p - %p = %ld, %d, %d, %d\n", fun, out + 5, disp, disp <= 0x7FFFFFFF, disp >= (-2147483648), -2147483648); + return NULL; + } + return out; +} + +uint8_t * retn(uint8_t * out) +{ + *(out++) = OP_RETN; + return out; +} + + diff -r 168b1a873895 -r 2bdad0f52f42 gen_x86.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen_x86.h Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,92 @@ +#ifndef GEN_X86_H_ +#define GEN_X86_H_ + +#include + +enum { + RAX = 0, + RCX, + RDX, + RBX, + RSP, + RBP, + RSI, + RDI, + AH, + CH, + DH, + BH, + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15 +} x86_regs; + +enum { + CC_O = 0, + CC_NO, + CC_C, + CC_NC, + CC_Z, + CC_NZ, + CC_BE, + CC_A, + CC_S, + CC_NS, + CC_P, + CC_NP, + CC_L, + CC_GE, + CC_LE, + CC_G +} x86_cc; + +enum { + SZ_B = 0, + SZ_W, + SZ_D, + SZ_Q +} x86_size; + +uint8_t * add_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * or_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * xor_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * add_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * or_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * xor_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * and_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * sub_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * cmp_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * add_i32r(uint8_t * out, int32_t val, uint8_t dst); +uint8_t * or_i32r(uint8_t * out, int32_t val, uint8_t dst); +uint8_t * xor_i32r(uint8_t * out, int32_t val, uint8_t dst); +uint8_t * and_i32r(uint8_t * out, int32_t val, uint8_t dst); +uint8_t * sub_i32r(uint8_t * out, int32_t val, uint8_t dst); +uint8_t * cmp_i32r(uint8_t * out, int32_t val, uint8_t dst); +uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * mov_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size); +uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size); +uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); +uint8_t * mov_i8r(uint8_t * out, uint8_t val, uint8_t dst); +uint8_t * mov_i16r(uint8_t * out, uint16_t val, uint8_t dst); +uint8_t * mov_i32r(uint8_t * out, uint32_t val, uint8_t dst); +uint8_t * pushf(uint8_t * out); +uint8_t * popf(uint8_t * out); +uint8_t * push_r(uint8_t * out, uint8_t reg); +uint8_t * pop_r(uint8_t * out, uint8_t reg); +uint8_t * setcc_r(uint8_t * out, uint8_t cc, uint8_t dst); +uint8_t * setcc_rind(uint8_t * out, uint8_t cc, uint8_t dst); +uint8_t * jcc(uint8_t * out, uint8_t cc, int32_t disp); +uint8_t * call(uint8_t * out, uint8_t * fun); +uint8_t * retn(uint8_t * out); + +#endif //GEN_X86_H_ + diff -r 168b1a873895 -r 2bdad0f52f42 m68k_to_x86.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m68k_to_x86.c Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,231 @@ +#include "gen_x86.h" +#include "m68k_to_x86.h" + + +#define BUS 4 +#define CYCLES RAX +#define LIMIT RBP +#define SCRATCH RCX +#define CONTEXT RSI + +#define FLAG_N RBX +#define FLAG_V BH +#define FLAG_Z RDX +#define FLAG_C DH + +typedef struct { + int32_t disp; + uint8_t mode; + uint8_t base; + uint8_t index; + uint8_t cycles; +} x86_ea; + +void handle_cycle_limit(); + +uint8_t * cycles(uint8_t * dst, uint32_t num) +{ + dst = add_i32r(dst, num, CYCLES); +} + +uint8_t * check_cycles(uint8_t * dst) Ivds +{ + dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); + dst = jcc(dst, CC_G, 5); + dst = call(dst, (char *)handle_cycle_limit); +} + +int8_t native_reg(m68k_op_info * op, x86_68k_options * opts) +{ + if (op->addr_mode == MODE_REG) { + return opts->dregs[op->params.regs.pri]; + } + if (op->addr_mode == MODE_AREG) { + return opts->aregs[op->params.regs.pri]; + } + return -1; +} + +uint8_t * translate_m68k_ea(m68k_op_info * op, x86_ea * dst, uint8_t * out, x86_68k_options * opts) +{ + int8_t reg = native_reg(op, opts); + if (reg >= 0) { + dst->mode = MODE_REG_DIRECT; + dst->base = reg; + return; + } + switch (op->addr_mode) + { + case MODE_REG: + case MODE_AREG: + dst->mode = MODE_DISPLACE8; + dst->base = CONTEXT; + dst->disp = (op->addr_mode = MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * op->params.regs.pri; + break; + case MODE_AREG_INDIRECT: + + break; + } +} + +uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) +{ + int8_t reg_a, reg_b, flags_reg; + uint8_t dir = 0; + int32_t offset; + switch(inst->op) + { + case M68K_ABCD: + case M68K_ADD: + case M68K_ADDX: + case M68K_AND: + case M68K_ANDI_CCR: + case M68K_ANDI_SR: + case M68K_ASL: + case M68K_ASR: + case M68K_BCC: + case M68K_BCHG: + case M68K_BCLR: + case M68K_BSET: + case M68K_BSR: + case M68K_BTST: + case M68K_CHK: + case M68K_CLR: + case M68K_CMP: + case M68K_DBCC: + case M68K_DIVS: + case M68K_DIVU: + case M68K_EOR: + case M68K_EORI_CCR: + case M68K_EORI_SR: + case M68K_EXG: + case M68K_EXT: + case M68K_ILLEGAL: + case M68K_JMP: + case M68K_JSR: + case M68K_LEA: + case M68K_LINK: + case M68K_LSL: + case M68K_LSR: + case M68K_MOVE: + + if ((inst->src.addr_mode == MODE_REG || inst->src.addr_mode == MODE_AREG || (inst->src.addr_mode == MODE_IMMEDIATE && inst->src.variant == VAR_QUICK)) && (inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)) { + dst = cycles(dst, BUS); + reg_a = native_reg(&(inst->src), opts); + reg_b = native_reg(&(inst->dst), opts); + dst = cycles(dst, BUS); + if (reg_a >= 0 && reg_b >= 0) { + dst = mov_rr(dst, reg_a, reg_b, inst->extra.size); + flags_reg = reg_b; + } else if(reg_a >= 0) { + offset = inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs); + dst = mov_rrdisp8(dst, reg_a, CONTEXT, offset + 4 * inst->dst.params.regs.pri, inst->extra.size); + flags_reg = reg_a; + } else if(reg_b >= 0) { + if (inst->src.addr_mode == MODE_REG) { + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->src.params.regs.pri, reg_b, inst->extra.size); + } else if(inst->src.addr_mode == MODE_AREG) { + dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, reg_b, inst->extra.size); + } else { + dst = mov_i32r(dst, inst->src.params.u32, reg_b); + } + flags_reg = reg_b; + } else { + + } + dst = mov_i8r(dst, 0, FLAG_V); + dst = mov_i8r(dst, 0, FLAG_C); + switch (inst->extra.size) + { + case OPSIZE_BYTE: + dst = cmp_i8r(dst, 0, reg_b, SZ_B); + break; + case OPSIZE_WORD: + dst = cmp_i8r(dst, 0, reg_b, SZ_W); + break; + case OPSIZE_LONG: + dst = cmp_i8r(dst, 0, reg_b, SZ_D); + break; + } + dst = setcc_r(dst, CC_Z, FLAG_Z); + dst = setcc_r(dst, CC_S, FLAG_N); + dst = check_cycles(dst); + } + + if (reg_a >= 0 && reg_b >= 0) { + dst = cycles(dst, BUS); + dst = mov_rr(dst, reg_a, reg_b, inst->extra.size); + dst = mov_i8r(dst, 0, FLAG_V); + dst = mov_i8r(dst, 0, FLAG_C); + switch (inst->extra.size) + { + case OPSIZE_BYTE: + dst = cmp_i8r(dst, 0, reg_b, SZ_B); + break; + case OPSIZE_WORD: + dst = cmp_i8r(dst, 0, reg_b, SZ_W); + break; + case OPSIZE_LONG: + dst = cmp_i8r(dst, 0, reg_b, SZ_D); + break; + } + dst = setcc_r(dst, CC_Z, FLAG_Z); + dst = setcc_r(dst, CC_S, FLAG_N); + dst = check_cycles(dst); + } else if(reg_a >= 0 || reg_b >= 0) { + if (reg_a >= 0) { + switch (inst->dst.addr_mode) + { + case MODE_REG: + dst = cycles(dst, BUS); + dst = mov_rr(dst, reg_a, reg_b, inst->extra.size); + dst = check_cycles(dst); + break; + case MODE_AREG: + break; + } + } else { + } + } + break; + case M68K_MOVE_CCR: + case M68K_MOVE_FROM_SR: + case M68K_MOVE_SR: + case M68K_MOVE_USP: + case M68K_MOVEM: + case M68K_MOVEP: + case M68K_MULS: + case M68K_MULU: + case M68K_NBCD: + case M68K_NEG: + case M68K_NEGX: + case M68K_NOP: + case M68K_NOT: + case M68K_OR: + case M68K_ORI_CCR: + case M68K_ORI_SR: + case M68K_PEA: + case M68K_RESET: + case M68K_ROL: + case M68K_ROR: + case M68K_ROXL: + case M68K_ROXR: + case M68K_RTE: + case M68K_RTR: + case M68K_RTS: + case M68K_SBCD: + case M68K_SCC: + case M68K_STOP: + case M68K_SUB: + case M68K_SUBX: + case M68K_SWAP: + case M68K_TAS: + case M68K_TRAP: + case M68K_TRAPV: + case M68K_TST: + case M68K_UNLK: + case M68K_INVALID: + break; + } +} + diff -r 168b1a873895 -r 2bdad0f52f42 m68k_to_x86.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m68k_to_x86.h Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,16 @@ +#include + +typedef struct { + uint32_t flags; + int8_t dregs[8]; + int8_t aregs[8]; +} x86_68k_options; + +typedef struct { + uint8_t flags[5]; + uint8_t status; + uint16_t reserved; + uint32_t dregs[8]; + uint32_t aregs[8]; +} m68k_context; + diff -r 168b1a873895 -r 2bdad0f52f42 mem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mem.c Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,10 @@ +#include +#include +#include "mem.h" + +void * alloc_code(size_t *size) +{ + *size += PAGE_SIZE - (*size & (PAGE_SIZE - 1)); + return mmap(NULL, *size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +} + diff -r 168b1a873895 -r 2bdad0f52f42 mem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mem.h Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,11 @@ +#ifndef MEM_H_ +#define MEM_H_ + +#include + +#define PAGE_SIZE 4096 + +void * alloc_code(size_t *size); + +#endif //MEM_H_ + diff -r 168b1a873895 -r 2bdad0f52f42 notes.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/notes.txt Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,67 @@ +cmp.w , Dn 4(1/0) + time +cmp.l , Dn 6(1/0) + time +cmp.w #num, Dn 4(1/0) + 4(1/0) +cmp.l #num, Dn 6(1/0) + 8(2/0) + +cmpi.w #num, Dn 8(2/0) +cmpi.l #num, Dn 14(3/0) + + +movem + +subtype field (bits 9-11) = 110 or 100 depending on direction +bit 8 = 0 +bit 7 = 1 +bit 6 = size + + + +x86-64 registers in 68K core + +1. native stack pointer +2. current cycle count +3. target cycle count +4. cartridge address +5. work ram address +6. scratch register +7. context pointer (contains 68K registers and memory pointers not in registers) +8. status register (maybe, depends on how well I can abuse native x86 status stuff) +Rest of registers used for holding 68K registers + +rax = cycle counter +bl = N flag +bh = V flag +rcx = scratch register +dl = Z flag +dh = C flag +rbp = target cycle count +rsi = context pointer +rdi = d0 +r8 = d1 +r9 = d2 +r10 = d3 +r11 = a0 +r12 = a1 +r13 = a6 +r14 = a7 +r15 = work ram address +r16 = cartridge address +rsp = native stack pointer + +68K context: +uint8_t flags[5]; +uint8_t pad??[3] +uint32_t dregs[8]; //8 + 4 * reg +uint32_t aregs[8]; //40 + 4 * reg +..... + +x86-64 registers in Z80 core + +ax = AF +bx = BC +cx = DE +dx = HL + +1. native stack pointer +2. current cycle count +3. target cycle count diff -r 168b1a873895 -r 2bdad0f52f42 test_x86.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_x86.c Tue Nov 27 09:28:13 2012 -0800 @@ -0,0 +1,41 @@ +#include "gen_x86.h" +#include +#include + +int main(int argc, char ** argv) +{ + uint8_t foo[512]; + uint8_t *cur = foo, *end; + cur = mov_rr(cur, RAX, RBX, SZ_B); + cur = mov_rr(cur, RCX, RDX, SZ_B); + cur = mov_rr(cur, R8, R9, SZ_B); + cur = mov_rr(cur, R8, RAX, SZ_B); + cur = mov_rr(cur, RAX, RBX, SZ_W); + cur = mov_rr(cur, R11, R12, SZ_W); + cur = mov_rr(cur, RAX, RBX, SZ_D); + cur = mov_rr(cur, RAX, RBX, SZ_Q); + cur = mov_i32r(cur, 5, RAX); + cur = mov_i32r(cur, 3, R8); + cur = mov_i8r(cur, 4, RSP); + cur = add_rr(cur, RAX, RBX, SZ_D); + cur = add_i8r(cur, 5, RAX); + cur = add_i8r(cur, 5, RBX); + cur = pushf(cur); + cur = popf(cur); + cur = setcc_r(cur, CC_S, RBX); + cur = setcc_r(cur, CC_Z, RDX); + cur = setcc_r(cur, CC_O, BH); + cur = setcc_r(cur, CC_C, DH); + cur = setcc_rind(cur, CC_C, RSI); + cur = mov_rrdisp8(cur, RCX, RSI, offsetof(m68k_context, dregs) + 4 * sizeof(uint32_t), SZ_D); + cur = mov_rdisp8r(cur, RSI, offsetof(m68k_context, dregs) + 5 * sizeof(uint32_t), RCX, SZ_D); + cur = mov_rrind(cur, DH, RSI, SZ_B); + cur = jcc(cur, CC_NZ, -2); + cur = jcc(cur, CC_Z, 0); + cur = jcc(cur, CC_LE, 0x7CA); + for (end = cur, cur = foo; cur != end; cur++) { + printf(" %X", *cur); + } + puts(""); + return 0; +}