changeset 0:2432d177e1ac

Initial work on M68K instruction decoding
author Mike Pavone <pavone@retrodev.com>
date Mon, 29 Oct 2012 01:18:38 -0700
parents
children 5a2c1da6dd0f
files 68kinst.c 68kinst.h fib.s68
diffstat 3 files changed, 263 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/68kinst.c	Mon Oct 29 01:18:38 2012 -0700
@@ -0,0 +1,92 @@
+#include "68kinst.h"
+
+void m68k_decode_op(uint16_t op, m68k_op_info *dst)
+{
+	uint8_t mode = (op >> 3) & 0x7;
+	uint8_t reg = op & 0x7;
+	dst->addr_mode = mode;
+	switch(mode)
+	{
+	case MODE_REG:
+	case MODE_AREG:
+		dst->params.regs.pri = reg;
+		break;
+	case MODE_
+	}
+}
+
+uint16_t * m68K_decode(uint16_t * istream, m68kinst * decoded)
+{
+	uint8_t optype = *istream >> 12;
+	uint8_t size;
+	uint8_t immed;
+	switch(optype)
+	{
+	case BIT_MOVEP_IMMED:
+		//TODO: Implement me
+		break;
+	case MOVE_BYTE:
+	case MOVE_LONG:
+	case MOVE_WORD:
+		decoded->op = M68K_MOVE;
+		decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG);
+		m68k_decode_op(*istream, &(decoded->src));
+		m68k_decode_op(((*istream >> 9) & 0x7) | , &(decoded->dst));
+		break;
+	case MISC:
+		//TODO: Implement me
+		break;
+	case QUICK_ARITH_LOOP:
+		size = (*istream >> 6) & 3;
+		if (size == 0x3) {
+			//DBcc, TRAPcc or Scc
+			decoded->extra.cond = (*istream >> 0x8) & 0xF;
+			switch ((*istream >> 3) & 0x7)
+			{
+			case 1: //DBcc
+				decoded->op = M68K_DBCC;
+				decoded->dst.addr_mode = MODE_REG;
+				decoded->dst.regs.pri = *istream & 0x7;
+				break;
+			case 7: //TRAPcc
+				decoded->op = M68K_TRAPCC;
+				decoded->src.addr_mode = MODE_PC_INDIRECT_ABS_IMMED;
+				decoded->src.regs.pri = MODE_IMMEDIATE;
+				//TODO: Figure out what to do with OPMODE and optional extention words
+				break;
+			default: //Scc
+				decoded->op = M68K_SCC;
+				M68k_decode_op(*istream, &(decoded->dst));
+				break;
+			}
+		} else {
+			//ADDQ, SUBQ
+			decoded->variant = VAR_QUICK;
+			decoded->extra.size = size;
+			decoded->src.addr_mode = MODE_PC_INDIRECT_ABS_IMMED;
+			decoded->src.regs.pri = MODE_IMMEDIATE;
+			immed = (*istream >> 9) & 0x7
+			if (!immed) {
+				immed = 8;
+			}
+			switch (size)
+			{
+			case OPSIZE_BYTE;
+				decoded->src.params.u8 = immed;
+				break;
+			case OPSIZE_WORD:
+				decoded->src.params.u16 = immed;
+				break;
+			case OPSIZE_LONG:
+				decoded->src.params.u38 = immed;
+				break;
+			}
+			if (*istream & 0x10) {
+				decoded->op = M68K_SUB;
+			} else {
+				decoded->op = M68K_ADD;
+			}
+		}
+		break;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/68kinst.h	Mon Oct 29 01:18:38 2012 -0700
@@ -0,0 +1,150 @@
+#include <stdint.h>
+
+typedef enum {
+	BIT_MOVEP_IMMED = 0,
+	MOVE_BYTE,
+	MOVE_LONG,
+	MOVE_WORD,
+	MISC,
+	QUICK_ARITH_LOOP,
+	BRANCH,
+	MOVEQ,
+	OR_DIV_SBCD,
+	SUB_SUBX,
+	RESERVED,
+	CMP_XOR,
+	AND_MUL_ABCD_EXG,
+	ADD_ADDX,
+	SHIFT_ROTATE,
+	COPROC
+} m68k_optypes;
+
+typedef enum {
+	M68K_ABCD,
+	M68K_ADD,
+	M68K_ADDX,
+	M68K_AND,
+	M68K_ANDI_CCR,
+	M68K_ANDI_SR,
+	M68K_ASL,
+	M68K_ASR,
+	M68K_BCC,
+	M68K_BCHG,
+	M68K_BCLR,
+	M68K_BSET,
+	M68K_BSR,
+	M68K_BTST,
+	M68K_CHK,
+	M68K_CLR,
+	M68K_CMP,
+	M68K_DBCC,
+	M68K_DIVS,
+	M68K_DIVU,
+	M68K_EOR,
+	M68K_EORI_CCR,
+	M68K_EORI_SR,
+	M68K_EXG,
+	M68K_EXT,
+	M68K_ILLEGAL,
+	M68K_JMP,
+	M68K_JSR,
+	M68K_LEA,
+	M68K_LINK
+	M68K_LSL,
+	M68K_LSR,
+	M68K_MOVE,
+	M68K_MOVE_CCR,
+	M68K_MOVE_FROM_SR,
+	M68K_MOVE_SR,
+	M68K_MOVE_USP,
+	M68K_MOVEM,
+	M68K_MOVEP,
+	M68K_MULS,
+	M68K_MULU,
+	M68K_NBCD,
+	M68K_NEG,
+	M68K_NEGX,
+	M68K_NOP,
+	M68K_NOT,
+	M68K_OR,
+	M68K_ORI_CCR,
+	M68K_ORI_SR,
+	M68K_PEA,
+	M68K_RESET,
+	M68K_ROL,
+	M68K_ROR,
+	M68K_ROXL,
+	M68K_ROXR,
+	M68K_RTE,
+	M68K_RTR,
+	M68K_RTS,
+	M68K_SBCD,
+	M68K_SCC,
+	M68K_STOP,
+	M68K_SUB,
+	M68K_SUBX,
+	M68K_SWAP,
+	M68K_TAS,
+	M68K_TRAP,
+	M68k_TRAPV
+	M68K_TST,
+	M68K_UNLNK
+} m68K_op;
+
+typedef enum {
+	VAR_NORMAL,
+	VAR_QUICK
+} m68K_variant;
+
+typedef enum {
+	OPSIZE_BYTE=0,
+	OPSIZE_WORD,
+	OPSIZE_LONG
+} m68K_opsizes;
+
+typedef enum {
+	MODE_REG = 0,
+	MODE_AREG,
+	MODE_AREG_INDIRECT,
+	MODE_AREG_POSTINC,
+	MODE_AREG_PREDEC,
+	MODE_AREG_DISPLACE,
+	MODE_AREG_INDEX_MEM, //bunch of relatively complicated modes
+	MODE_PC_INDIRECT_ABS_IMMED //Modes that use the program counter, an absolute address or immediate value
+} m68k_addr_modes;
+
+typedef enum {
+	MODE_ABSOLUTE=0,
+	MODE_PC_DISPLACE,
+	MODE_PC_INDEX,
+	MODE_IMMEDIATE
+} m68k_addr_extended;
+
+typedef struct {
+	uint8_t addr_mode;
+	union {
+		struct {
+			uint8_t pri;
+			uint8_t sec;
+			int32_t displacement;
+		} regs;
+		uint8_t u8;
+		uint16_t u16;
+		uint32_t u32;
+	} params;
+} m68k_op_info;
+
+typedef struct {
+	uint8_t op;
+	uint8_t variant;
+	union {
+		uint8_t size;
+		uint8_t cond;
+	} extra;
+	m68k_op_info src;
+	m68k_op_info dst;
+} m68kinst;
+
+uint16_t * m68K_decode(uint16_t * istream, m68kinst * dst);
+uint32_t m68k_cycles(m68kinst * inst);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fib.s68	Mon Oct 29 01:18:38 2012 -0700
@@ -0,0 +1,21 @@
+	lea 0, a7
+	moveq #10, d0
+	bsr fib
+	illegal
+fib:
+	cmp #2, d0
+	blt base
+	subq #1, d0
+	move.l d0, -(a7)
+	bsr fib
+	move.l (a7), d1
+	exg d0, d1
+	move.l d1, (a7)
+	subq #1, d0
+	bsr fib
+	move.l (a7)+, d1
+	add.l d1, d0
+	rts
+base:
+	moveq #1, d0
+	rts