view 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 source

#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;
	}
}