summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2012-10-29 01:18:38 -0700
committerMike Pavone <pavone@retrodev.com>2012-10-29 01:18:38 -0700
commit7c49618ca54c5178f7a3f5db21eaff3bf16e58b7 (patch)
tree2e66736eebeb6ed359296c159e6ecf23a079cd4a
Initial work on M68K instruction decoding
-rw-r--r--68kinst.c92
-rw-r--r--68kinst.h150
-rw-r--r--fib.s6821
3 files changed, 263 insertions, 0 deletions
diff --git a/68kinst.c b/68kinst.c
new file mode 100644
index 0000000..dcb9501
--- /dev/null
+++ b/68kinst.c
@@ -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;
+ }
+}
diff --git a/68kinst.h b/68kinst.h
new file mode 100644
index 0000000..a47b685
--- /dev/null
+++ b/68kinst.h
@@ -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);
+
diff --git a/fib.s68 b/fib.s68
new file mode 100644
index 0000000..1fa08d4
--- /dev/null
+++ b/fib.s68
@@ -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