diff m68k_to_x86.c @ 14:2bdad0f52f42

x86 code gen, initial work on translator
author Mike Pavone <pavone@retrodev.com>
date Tue, 27 Nov 2012 09:28:13 -0800
parents
children 3e7bfde7606e
line wrap: on
line diff
--- /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;
+	}
+}
+