diff m68k_core.c @ 582:c05fcbfe1b1a

Refactored translate_m68k so that it contains no host-cpu specific code and moved it to m68k_core.c
author Michael Pavone <pavone@retrodev.com>
date Fri, 07 Mar 2014 17:42:29 -0800
parents 9f40aa5243c2
children b6713c1b6f55
line wrap: on
line diff
--- a/m68k_core.c	Wed Mar 05 19:26:53 2014 -0800
+++ b/m68k_core.c	Fri Mar 07 17:42:29 2014 -0800
@@ -326,6 +326,34 @@
 	jmp(code, opts->trap);
 }
 
+void translate_m68k_move_usp(m68k_options *opts, m68kinst *inst)
+{
+	cycles(&opts->gen, BUS);
+	int8_t reg;
+	if (inst->src.addr_mode == MODE_UNUSED) {
+		reg = native_reg(&inst->dst, opts);
+		if (reg < 0) {
+			reg = opts->gen.scratch1;
+		}
+		areg_to_native(opts, 8, reg);
+		if (reg == opts->gen.scratch1) {
+			native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
+		}
+	} else {
+		reg = native_reg(&inst->src, opts);
+		if (reg < 0) {
+			reg = opts->gen.scratch1;
+			areg_to_native(opts, inst->src.params.regs.pri, reg);
+		}
+		native_to_areg(opts, reg, 8);
+	}
+}
+
+void translate_m68k_nop(m68k_options *opts, m68kinst *inst)
+{
+	cycles(&opts->gen, BUS);
+}
+
 void swap_ssp_usp(m68k_options * opts)
 {
 	areg_to_native(opts, 7, opts->gen.scratch2);
@@ -435,6 +463,150 @@
 	}
 }
 
+typedef enum {
+	RAW_FUNC = 1,
+	BINARY_ARITH,
+	UNARY_ARITH,
+	OP_FUNC
+} impl_type;
+
+typedef void (*raw_fun)(m68k_options * opts, m68kinst *inst);
+typedef void (*op_fun)(m68k_options * opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
+
+typedef struct {
+	union {
+		raw_fun  raw;
+		uint32_t flag_mask;
+		op_fun   op;
+	} impl;
+	impl_type itype;
+} impl_info;
+
+#define RAW_IMPL(inst, fun)     [inst] = { .impl = { .raw = fun }, .itype = RAW_FUNC }
+#define OP_IMPL(inst, fun)      [inst] = { .impl = { .op = fun }, .itype = OP_FUNC }
+#define UNARY_IMPL(inst, mask)  [inst] = { .impl = { .flag_mask = mask }, .itype = UNARY_ARITH }
+#define BINARY_IMPL(inst, mask) [inst] = { .impl = { .flag_mask = mask}, .itype = BINARY_ARITH }
+
+impl_info m68k_impls[] = {
+	//math
+	BINARY_IMPL(M68K_ADD, X|N|Z|V|C),
+	BINARY_IMPL(M68K_SUB, X|N|Z|V|C),
+	//z flag is special cased for ADDX/SUBX
+	BINARY_IMPL(M68K_ADDX, X|N|V|C),
+	BINARY_IMPL(M68K_SUBX, X|N|V|C),
+	OP_IMPL(M68K_ABCD, translate_m68k_abcd_sbcd),
+	OP_IMPL(M68K_SBCD, translate_m68k_abcd_sbcd),
+	BINARY_IMPL(M68K_AND, N|Z|V0|C0),
+	BINARY_IMPL(M68K_EOR, N|Z|V0|C0),
+	BINARY_IMPL(M68K_OR, N|Z|V0|C0),
+	RAW_IMPL(M68K_CMP, translate_m68k_cmp),
+	OP_IMPL(M68K_DIVS, translate_m68k_div),
+	OP_IMPL(M68K_DIVU, translate_m68k_div),
+	OP_IMPL(M68K_MULS, translate_m68k_mul),
+	OP_IMPL(M68K_MULU, translate_m68k_mul),
+	RAW_IMPL(M68K_EXT, translate_m68k_ext),
+	UNARY_IMPL(M68K_NEG, X|N|Z|V|C),
+	OP_IMPL(M68K_NEGX, translate_m68k_negx),
+	UNARY_IMPL(M68K_NOT, X|N|Z|V|C),
+	UNARY_IMPL(M68K_TST, N|Z|V0|C0),
+
+	//shift/rotate
+	OP_IMPL(M68K_ASL, translate_m68k_sl),
+	OP_IMPL(M68K_LSL, translate_m68k_sl),
+	OP_IMPL(M68K_ASR, translate_m68k_asr),
+	OP_IMPL(M68K_LSR, translate_m68k_lsr),
+	OP_IMPL(M68K_ROL, translate_m68k_rot),
+	OP_IMPL(M68K_ROR, translate_m68k_rot),
+	OP_IMPL(M68K_ROXL, translate_m68k_rot),
+	OP_IMPL(M68K_ROXR, translate_m68k_rot),
+	UNARY_IMPL(M68K_SWAP, N|Z|V0|C0),
+
+	//bit
+	OP_IMPL(M68K_BCHG, translate_m68k_bit),
+	OP_IMPL(M68K_BCLR, translate_m68k_bit),
+	OP_IMPL(M68K_BSET, translate_m68k_bit),
+	OP_IMPL(M68K_BTST, translate_m68k_bit),
+
+	//data movement
+	RAW_IMPL(M68K_MOVE, translate_m68k_move),
+	RAW_IMPL(M68K_MOVEM, translate_m68k_movem),
+	RAW_IMPL(M68K_MOVEP, translate_m68k_movep),
+	RAW_IMPL(M68K_MOVE_USP, translate_m68k_move_usp),
+	RAW_IMPL(M68K_LEA, translate_m68k_lea_pea),
+	RAW_IMPL(M68K_PEA, translate_m68k_lea_pea),
+	RAW_IMPL(M68K_CLR, translate_m68k_clr),
+	OP_IMPL(M68K_EXG, translate_m68k_exg),
+	RAW_IMPL(M68K_SCC, translate_m68k_scc),
+
+	//function calls and branches
+	RAW_IMPL(M68K_BCC, translate_m68k_bcc),
+	RAW_IMPL(M68K_BSR, translate_m68k_bsr),
+	RAW_IMPL(M68K_DBCC, translate_m68k_dbcc),
+	RAW_IMPL(M68K_JMP, translate_m68k_jmp_jsr),
+	RAW_IMPL(M68K_JSR, translate_m68k_jmp_jsr),
+	RAW_IMPL(M68K_RTS, translate_m68k_rts),
+	RAW_IMPL(M68K_RTE, translate_m68k_rte),
+	RAW_IMPL(M68K_RTR, translate_m68k_rtr),
+	RAW_IMPL(M68K_LINK, translate_m68k_link),
+	RAW_IMPL(M68K_UNLK, translate_m68k_unlk),
+
+	//SR/CCR stuff
+	RAW_IMPL(M68K_ANDI_CCR, translate_m68k_andi_ccr_sr),
+	RAW_IMPL(M68K_ANDI_SR, translate_m68k_andi_ccr_sr),
+	RAW_IMPL(M68K_EORI_CCR, translate_m68k_eori_ccr_sr),
+	RAW_IMPL(M68K_EORI_SR, translate_m68k_eori_ccr_sr),
+	RAW_IMPL(M68K_ORI_CCR, translate_m68k_ori_ccr_sr),
+	RAW_IMPL(M68K_ORI_SR, translate_m68k_ori_ccr_sr),
+	OP_IMPL(M68K_MOVE_CCR, translate_m68k_move_ccr_sr),
+	OP_IMPL(M68K_MOVE_SR, translate_m68k_move_ccr_sr),
+	OP_IMPL(M68K_MOVE_FROM_SR, translate_m68k_move_from_sr),
+	RAW_IMPL(M68K_STOP, translate_m68k_stop),
+
+	//traps
+	OP_IMPL(M68K_CHK, translate_m68k_chk),
+	RAW_IMPL(M68K_TRAP, translate_m68k_trap),
+	RAW_IMPL(M68K_ILLEGAL, translate_m68k_illegal),
+	RAW_IMPL(M68K_INVALID, translate_m68k_invalid),
+
+	//misc
+	RAW_IMPL(M68K_NOP, translate_m68k_nop),
+	RAW_IMPL(M68K_RESET, translate_m68k_reset),
+
+	//currently unimplemented
+	//M68K_NBCD
+	//M68K_TAS
+	//M68K_TRAPV
+};
+
+void translate_m68k(m68k_options * opts, m68kinst * inst)
+{
+	check_cycles_int(&opts->gen, inst->address);
+	impl_info * info = m68k_impls + inst->op;
+	if (info->itype == RAW_FUNC) {
+		info->impl.raw(opts, inst);
+		return;
+	}
+
+	host_ea src_op, dst_op;
+	if (inst->src.addr_mode != MODE_UNUSED) {
+		translate_m68k_op(inst, &src_op, opts, 0);
+	}
+	if (inst->dst.addr_mode != MODE_UNUSED) {
+		translate_m68k_op(inst, &dst_op, opts, 1);
+	}
+	if (info->itype == OP_FUNC) {
+		info->impl.op(opts, inst, &src_op, &dst_op);
+	} else if (info->itype == BINARY_ARITH) {
+		translate_m68k_arith(opts, inst, info->impl.flag_mask, &src_op, &dst_op);
+	} else if (info->itype == UNARY_ARITH) {
+		translate_m68k_unary(opts, inst, info->impl.flag_mask, inst->dst.addr_mode != MODE_UNUSED ? &dst_op : &src_op);
+	} else {
+		m68k_disasm(inst, disasm_buf);
+		printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op);
+		exit(1);
+	}
+}
+
 void translate_m68k_stream(uint32_t address, m68k_context * context)
 {
 	m68kinst instbuf;