# HG changeset patch # User Mike Pavone # Date 1351498718 25200 # Node ID 2432d177e1ac62e9e449e6b3fa1764c67acd2c58 Initial work on M68K instruction decoding diff -r 000000000000 -r 2432d177e1ac 68kinst.c --- /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; + } +} diff -r 000000000000 -r 2432d177e1ac 68kinst.h --- /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 + +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 -r 000000000000 -r 2432d177e1ac fib.s68 --- /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