summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2012-11-27 09:28:13 -0800
committerMike Pavone <pavone@retrodev.com>2012-11-27 09:28:13 -0800
commit707e8f0e6a9d5518ecb91afdcc1cf26e35eb82a3 (patch)
treea9491003e628ebc692ed8779a8362a51a251c70f
parentd3590618c3889ed92db9d8e848820b52da68f9f2 (diff)
x86 code gen, initial work on translator
-rw-r--r--68kinst.h5
-rw-r--r--gen_x86.c512
-rw-r--r--gen_x86.h92
-rw-r--r--m68k_to_x86.c231
-rw-r--r--m68k_to_x86.h16
-rw-r--r--mem.c10
-rw-r--r--mem.h11
-rw-r--r--notes.txt67
-rw-r--r--test_x86.c41
9 files changed, 985 insertions, 0 deletions
diff --git a/68kinst.h b/68kinst.h
index 03da053..8b5a089 100644
--- a/68kinst.h
+++ b/68kinst.h
@@ -1,3 +1,6 @@
+#ifndef M68KINST_H_
+#define M68KINST_H_
+
#include <stdint.h>
typedef enum {
@@ -176,3 +179,5 @@ uint16_t * m68K_decode(uint16_t * istream, m68kinst * dst);
uint32_t m68k_cycles(m68kinst * inst);
int m68K_disasm(m68kinst * decoded, char * dst);
+#endif
+
diff --git a/gen_x86.c b/gen_x86.c
new file mode 100644
index 0000000..6dcc444
--- /dev/null
+++ b/gen_x86.c
@@ -0,0 +1,512 @@
+#include "gen_x86.h"
+#include "68kinst.h"
+#include <stddef.h>
+#include <stdio.h>
+
+#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 --git a/gen_x86.h b/gen_x86.h
new file mode 100644
index 0000000..c240919
--- /dev/null
+++ b/gen_x86.h
@@ -0,0 +1,92 @@
+#ifndef GEN_X86_H_
+#define GEN_X86_H_
+
+#include <stdint.h>
+
+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 --git a/m68k_to_x86.c b/m68k_to_x86.c
new file mode 100644
index 0000000..6cdb16a
--- /dev/null
+++ b/m68k_to_x86.c
@@ -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 --git a/m68k_to_x86.h b/m68k_to_x86.h
new file mode 100644
index 0000000..c287d6f
--- /dev/null
+++ b/m68k_to_x86.h
@@ -0,0 +1,16 @@
+#include <stdint.h>
+
+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 --git a/mem.c b/mem.c
new file mode 100644
index 0000000..c3f03a4
--- /dev/null
+++ b/mem.c
@@ -0,0 +1,10 @@
+#include <sys/mman.h>
+#include <stddef.h>
+#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 --git a/mem.h b/mem.h
new file mode 100644
index 0000000..22b4a79
--- /dev/null
+++ b/mem.h
@@ -0,0 +1,11 @@
+#ifndef MEM_H_
+#define MEM_H_
+
+#include <stddef.h>
+
+#define PAGE_SIZE 4096
+
+void * alloc_code(size_t *size);
+
+#endif //MEM_H_
+
diff --git a/notes.txt b/notes.txt
new file mode 100644
index 0000000..f3f54e7
--- /dev/null
+++ b/notes.txt
@@ -0,0 +1,67 @@
+cmp.w <ea>, Dn 4(1/0) + <ea> time
+cmp.l <ea>, Dn 6(1/0) + <ea> 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 --git a/test_x86.c b/test_x86.c
new file mode 100644
index 0000000..05acd27
--- /dev/null
+++ b/test_x86.c
@@ -0,0 +1,41 @@
+#include "gen_x86.h"
+#include <stdio.h>
+#include <stddef.h>
+
+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;
+}