pavone@467: /* pavone@467: Copyright 2013 Michael Pavone pavone@518: This file is part of BlastEm. pavone@467: BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. pavone@467: */ pavone@0: #include "68kinst.h" pavone@2: #include pavone@2: #include pavone@2: pavone@2: uint32_t sign_extend16(uint32_t val) pavone@2: { pavone@2: return (val & 0x8000) ? val | 0xFFFF0000 : val; pavone@2: } pavone@0: pavone@2: uint32_t sign_extend8(uint32_t val) pavone@0: { pavone@2: return (val & 0x80) ? val | 0xFFFFFF00 : val; pavone@2: } pavone@2: pavone@2: uint16_t *m68k_decode_op_ex(uint16_t *cur, uint8_t mode, uint8_t reg, uint8_t size, m68k_op_info *dst) pavone@2: { pavone@638: uint16_t ext, tmp; pavone@0: dst->addr_mode = mode; pavone@0: switch(mode) pavone@0: { pavone@0: case MODE_REG: pavone@0: case MODE_AREG: pavone@2: case MODE_AREG_INDIRECT: pavone@2: case MODE_AREG_POSTINC: pavone@2: case MODE_AREG_PREDEC: pavone@0: dst->params.regs.pri = reg; pavone@0: break; pavone@2: case MODE_AREG_DISPLACE: pavone@2: ext = *(++cur); pavone@2: dst->params.regs.pri = reg; pavone@2: dst->params.regs.displacement = sign_extend16(ext); pavone@2: break; pavone@2: case MODE_AREG_INDEX_MEM: pavone@638: dst->params.regs.pri = reg; pavone@638: ext = *(++cur); pavone@638: dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit pavone@638: #ifdef M68020 pavone@638: dst->params.regs.scale = ext >> 9 & 3; pavone@638: if (ext & 0x100) pavone@638: { pavone@638: dst->params.regs.disp_sizes = ext >> 4 & 3; pavone@638: switch (dst->params.regs.disp_sizes) pavone@638: { pavone@638: case 0: pavone@638: //reserved pavone@638: return NULL; pavone@638: case 1: pavone@638: dst->params.regs.displacement = 0; pavone@638: break; pavone@638: case 2: pavone@638: dst->params.regs.displacement = sign_extend16(*(cur++)); pavone@638: break; pavone@638: case 3: pavone@638: tmp = *(cur++); pavone@638: dst->params.regs.displacement = tmp << 16 | *(cur++); pavone@638: break; pavone@638: } pavone@638: if (ext & 0x3) pavone@638: { pavone@638: //memory indirect pavone@638: switch (ext & 0xC4) pavone@638: { pavone@638: case 0x00: pavone@638: dst->addr_mode = MODE_AREG_PREINDEX; pavone@638: break; pavone@638: case 0x04: pavone@638: dst->addr_mode = MODE_AREG_POSTINDEX; pavone@638: break; pavone@638: case 0x40: pavone@638: dst->addr_mode = MODE_AREG_MEM_INDIRECT; pavone@638: break; pavone@638: case 0x80: pavone@638: dst->addr_mode = MODE_PREINDEX; pavone@638: break; pavone@638: case 0x84: pavone@638: dst->addr_mode = MODE_POSTINDEX; pavone@638: break; pavone@638: case 0xC0: pavone@638: dst->addr_mode = MODE_MEM_INDIRECT; pavone@638: break; pavone@638: } pavone@638: dst->params.regs.disp_sizes |= ext << 4 & 0x30; pavone@638: switch (ext & 0x3) pavone@638: { pavone@638: case 0: pavone@638: //reserved pavone@638: return NULL; pavone@638: case 1: pavone@638: dst->params.regs.outer_disp = 0; pavone@638: break; pavone@638: case 2: pavone@638: dst->params.regs.outer_disp = sign_extend16(*(cur++)); pavone@638: break; pavone@638: case 3: pavone@638: tmp = *(cur++); pavone@638: dst->params.regs.outer_disp = tmp << 16 | *(cur++); pavone@638: break; pavone@638: } pavone@638: } else { pavone@638: switch (ext >> 6 & 3) pavone@638: { pavone@638: case 0: pavone@638: dst->addr_mode = MODE_AREG_INDEX_BASE_DISP; pavone@638: break; pavone@638: case 1: pavone@638: dst->addr_mode = MODE_AREG_BASE_DISP; pavone@638: break; pavone@638: case 2: pavone@638: dst->addr_mode = MODE_INDEX_BASE_DISP; pavone@638: break; pavone@638: case 3: pavone@638: dst->addr_mode = MODE_BASE_DISP; pavone@638: break; pavone@638: } pavone@638: } pavone@638: } else { pavone@638: #endif pavone@79: dst->addr_mode = MODE_AREG_INDEX_DISP8; pavone@79: dst->params.regs.displacement = sign_extend8(ext&0xFF); pavone@638: #ifdef M68020 pavone@638: } pavone@638: #endif pavone@2: break; pavone@2: case MODE_PC_INDIRECT_ABS_IMMED: pavone@2: switch(reg) pavone@2: { pavone@2: case 0: pavone@2: dst->addr_mode = MODE_ABSOLUTE_SHORT; pavone@2: ext = *(++cur); pavone@15: dst->params.immed = sign_extend16(ext); pavone@2: break; pavone@2: case 1: pavone@2: dst->addr_mode = MODE_ABSOLUTE; pavone@2: ext = *(++cur); pavone@15: dst->params.immed = ext << 16 | *(++cur); pavone@2: break; pavone@79: case 3: pavone@638: ext = *(++cur); pavone@638: dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit pavone@638: #ifdef M68020 pavone@638: dst->params.regs.scale = ext >> 9 & 3; pavone@638: if (ext & 0x100) pavone@638: { pavone@638: dst->params.regs.disp_sizes = ext >> 4 & 3; pavone@638: switch (dst->params.regs.disp_sizes) pavone@638: { pavone@638: case 0: pavone@638: //reserved pavone@638: return NULL; pavone@638: case 1: pavone@638: dst->params.regs.displacement = 0; pavone@638: break; pavone@638: case 2: pavone@638: dst->params.regs.displacement = sign_extend16(*(cur++)); pavone@638: break; pavone@638: case 3: pavone@638: tmp = *(cur++); pavone@638: dst->params.regs.displacement = tmp << 16 | *(cur++); pavone@638: break; pavone@638: } pavone@638: if (ext & 0x3) pavone@638: { pavone@638: //memory indirect pavone@638: switch (ext & 0xC4) pavone@638: { pavone@638: case 0x00: pavone@638: dst->addr_mode = MODE_PC_PREINDEX; pavone@638: break; pavone@638: case 0x04: pavone@638: dst->addr_mode = MODE_PC_POSTINDEX; pavone@638: break; pavone@638: case 0x40: pavone@638: dst->addr_mode = MODE_PC_MEM_INDIRECT; pavone@638: break; pavone@638: case 0x80: pavone@638: dst->addr_mode = MODE_ZPC_PREINDEX; pavone@638: break; pavone@638: case 0x84: pavone@638: dst->addr_mode = MODE_ZPC_POSTINDEX; pavone@638: break; pavone@638: case 0xC0: pavone@638: dst->addr_mode = MODE_ZPC_MEM_INDIRECT; pavone@638: break; pavone@638: } pavone@638: dst->params.regs.disp_sizes |= ext << 4 & 0x30; pavone@638: switch (ext & 0x3) pavone@638: { pavone@638: case 0: pavone@638: //reserved pavone@638: return NULL; pavone@638: case 1: pavone@638: dst->params.regs.outer_disp = 0; pavone@638: break; pavone@638: case 2: pavone@638: dst->params.regs.outer_disp = sign_extend16(*(cur++)); pavone@638: break; pavone@638: case 3: pavone@638: tmp = *(cur++); pavone@638: dst->params.regs.outer_disp = tmp << 16 | *(cur++); pavone@638: break; pavone@638: } pavone@638: } else { pavone@638: switch (ext >> 6 & 3) pavone@638: { pavone@638: case 0: pavone@638: dst->addr_mode = MODE_PC_INDEX_BASE_DISP; pavone@638: break; pavone@638: case 1: pavone@638: dst->addr_mode = MODE_PC_BASE_DISP; pavone@638: break; pavone@638: case 2: pavone@638: dst->addr_mode = MODE_ZPC_INDEX_BASE_DISP; pavone@638: break; pavone@638: case 3: pavone@638: dst->addr_mode = MODE_ZPC_BASE_DISP; pavone@638: break; pavone@638: } pavone@638: } pavone@638: } else { pavone@638: #endif pavone@638: dst->addr_mode = MODE_PC_INDEX_DISP8; pavone@638: dst->params.regs.displacement = sign_extend8(ext&0xFF); pavone@638: #ifdef M68020 pavone@638: } pavone@638: #endif pavone@95: break; pavone@2: case 2: pavone@2: dst->addr_mode = MODE_PC_DISPLACE; pavone@2: ext = *(++cur); pavone@2: dst->params.regs.displacement = sign_extend16(ext); pavone@2: break; pavone@2: case 4: pavone@2: dst->addr_mode = MODE_IMMEDIATE; pavone@2: ext = *(++cur); pavone@2: switch (size) pavone@2: { pavone@2: case OPSIZE_BYTE: pavone@15: dst->params.immed = ext & 0xFF; pavone@2: break; pavone@2: case OPSIZE_WORD: pavone@15: dst->params.immed = ext; pavone@2: break; pavone@2: case OPSIZE_LONG: pavone@15: dst->params.immed = ext << 16 | *(++cur); pavone@2: break; pavone@2: } pavone@2: break; pavone@176: default: pavone@176: return NULL; pavone@2: } pavone@2: break; pavone@0: } pavone@2: return cur; pavone@2: } pavone@2: pavone@823: uint8_t m68k_valid_immed_dst(m68k_op_info *dst) pavone@823: { pavone@823: if (dst->addr_mode == MODE_AREG || dst->addr_mode == MODE_IMMEDIATE) { pavone@823: return 0; pavone@823: } pavone@823: return 1; pavone@823: } pavone@823: pavone@823: uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst) pavone@823: { pavone@823: if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) { pavone@823: return 0; pavone@823: } pavone@823: return 1; pavone@823: } pavone@823: pavone@2: uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst) pavone@2: { pavone@2: uint8_t mode = (*cur >> 3) & 0x7; pavone@2: uint8_t reg = *cur & 0x7; pavone@2: return m68k_decode_op_ex(cur, mode, reg, size, dst); pavone@2: } pavone@2: pavone@2: void m68k_decode_cond(uint16_t op, m68kinst * decoded) pavone@2: { pavone@2: decoded->extra.cond = (op >> 0x8) & 0xF; pavone@2: } pavone@2: pavone@18: uint8_t m68k_reg_quick_field(uint16_t op) pavone@2: { pavone@2: return (op >> 9) & 0x7; pavone@0: } pavone@0: pavone@18: uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address) pavone@0: { pavone@176: uint16_t *start = istream; pavone@0: uint8_t optype = *istream >> 12; pavone@0: uint8_t size; pavone@4: uint8_t reg; pavone@4: uint8_t opmode; pavone@2: uint32_t immed; pavone@2: decoded->op = M68K_INVALID; pavone@2: decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED; pavone@2: decoded->variant = VAR_NORMAL; pavone@18: decoded->address = address; pavone@0: switch(optype) pavone@0: { pavone@0: case BIT_MOVEP_IMMED: pavone@163: if ((*istream & 0x138) == 0x108) { pavone@163: //MOVEP pavone@163: decoded->op = M68K_MOVEP; pavone@163: decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; pavone@163: if (*istream & 0x80) { pavone@163: //memory dest pavone@163: decoded->src.addr_mode = MODE_REG; pavone@163: decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); pavone@163: decoded->dst.addr_mode = MODE_AREG_DISPLACE; pavone@163: decoded->dst.params.regs.pri = *istream & 0x7; pavone@163: decoded->dst.params.regs.displacement = *(++istream); pavone@163: } else { pavone@163: //memory source pavone@163: decoded->dst.addr_mode = MODE_REG; pavone@163: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@163: decoded->src.addr_mode = MODE_AREG_DISPLACE; pavone@163: decoded->src.params.regs.pri = *istream & 0x7; pavone@163: decoded->src.params.regs.displacement = *(++istream); pavone@163: } pavone@163: } else if (*istream & 0x100) { pavone@4: //BTST, BCHG, BCLR, BSET pavone@4: switch ((*istream >> 6) & 0x3) pavone@4: { pavone@4: case 0: pavone@4: decoded->op = M68K_BTST; pavone@4: break; pavone@4: case 1: pavone@4: decoded->op = M68K_BCHG; pavone@4: break; pavone@4: case 2: pavone@4: decoded->op = M68K_BCLR; pavone@4: break; pavone@4: case 3: pavone@4: decoded->op = M68K_BSET; pavone@4: break; pavone@4: } pavone@4: decoded->src.addr_mode = MODE_REG; pavone@18: decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); pavone@61: decoded->extra.size = OPSIZE_BYTE; pavone@61: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@61: if (decoded->dst.addr_mode == MODE_REG) { pavone@61: decoded->extra.size = OPSIZE_LONG; pavone@61: } pavone@8: } else if ((*istream & 0xF00) == 0x800) { pavone@12: //BTST, BCHG, BCLR, BSET pavone@12: switch ((*istream >> 6) & 0x3) pavone@12: { pavone@12: case 0: pavone@12: decoded->op = M68K_BTST; pavone@12: break; pavone@12: case 1: pavone@12: decoded->op = M68K_BCHG; pavone@12: break; pavone@12: case 2: pavone@12: decoded->op = M68K_BCLR; pavone@12: break; pavone@12: case 3: pavone@12: decoded->op = M68K_BSET; pavone@12: break; pavone@12: } pavone@12: opmode = (*istream >> 3) & 0x7; pavone@12: reg = *istream & 0x7; pavone@61: decoded->src.addr_mode = MODE_IMMEDIATE_WORD; pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@12: decoded->extra.size = OPSIZE_BYTE; pavone@61: istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@61: if (decoded->dst.addr_mode == MODE_REG) { pavone@61: decoded->extra.size = OPSIZE_LONG; pavone@61: } pavone@8: } else if ((*istream & 0xC0) == 0xC0) { pavone@8: #ifdef M68020 pavone@8: //CMP2, CHK2, CAS, CAS2, RTM, CALLM pavone@8: #endif pavone@4: } else { pavone@4: switch ((*istream >> 9) & 0x7) pavone@4: { pavone@4: case 0: pavone@4: if ((*istream & 0xFF) == 0x3C) { pavone@4: decoded->op = M68K_ORI_CCR; pavone@4: decoded->extra.size = OPSIZE_BYTE; pavone@4: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@4: } else if((*istream & 0xFF) == 0x7C) { pavone@4: decoded->op = M68K_ORI_SR; pavone@4: decoded->extra.size = OPSIZE_WORD; pavone@4: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream); pavone@4: } else { pavone@8: decoded->op = M68K_OR; pavone@8: decoded->variant = VAR_IMMEDIATE; pavone@8: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@8: decoded->extra.size = size = (*istream >> 6) & 3; pavone@8: reg = *istream & 0x7; pavone@8: opmode = (*istream >> 3) & 0x7; pavone@8: switch (size) pavone@8: { pavone@8: case OPSIZE_BYTE: pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@8: break; pavone@8: case OPSIZE_WORD: pavone@15: decoded->src.params.immed = *(++istream); pavone@8: break; pavone@8: case OPSIZE_LONG: pavone@8: immed = *(++istream); pavone@15: decoded->src.params.immed = immed << 16 | *(++istream); pavone@8: break; pavone@4: } pavone@8: istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); pavone@823: if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@4: } pavone@4: break; pavone@4: case 1: pavone@8: //ANDI, ANDI to CCR, ANDI to SR pavone@5: if ((*istream & 0xFF) == 0x3C) { pavone@5: decoded->op = M68K_ANDI_CCR; pavone@5: decoded->extra.size = OPSIZE_BYTE; pavone@5: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@5: } else if((*istream & 0xFF) == 0x7C) { pavone@5: decoded->op = M68K_ANDI_SR; pavone@5: decoded->extra.size = OPSIZE_WORD; pavone@5: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream); pavone@5: } else { pavone@8: decoded->op = M68K_AND; pavone@8: decoded->variant = VAR_IMMEDIATE; pavone@5: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@5: decoded->extra.size = size = (*istream >> 6) & 3; pavone@5: reg = *istream & 0x7; pavone@5: opmode = (*istream >> 3) & 0x7; pavone@5: switch (size) pavone@5: { pavone@5: case OPSIZE_BYTE: pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@5: break; pavone@5: case OPSIZE_WORD: pavone@15: decoded->src.params.immed = *(++istream); pavone@5: break; pavone@5: case OPSIZE_LONG: pavone@5: immed = *(++istream); pavone@15: decoded->src.params.immed = immed << 16 | *(++istream); pavone@5: break; pavone@5: } pavone@5: istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); pavone@823: if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@5: } pavone@4: break; pavone@8: case 2: pavone@8: decoded->op = M68K_SUB; pavone@8: decoded->variant = VAR_IMMEDIATE; pavone@8: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@8: decoded->extra.size = size = (*istream >> 6) & 3; pavone@8: reg = *istream & 0x7; pavone@8: opmode = (*istream >> 3) & 0x7; pavone@8: switch (size) pavone@8: { pavone@8: case OPSIZE_BYTE: pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@8: break; pavone@8: case OPSIZE_WORD: pavone@15: decoded->src.params.immed = *(++istream); pavone@8: break; pavone@8: case OPSIZE_LONG: pavone@8: immed = *(++istream); pavone@15: decoded->src.params.immed = immed << 16 | *(++istream); pavone@8: break; pavone@8: } pavone@8: istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); pavone@823: if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@8: break; pavone@4: case 3: pavone@8: decoded->op = M68K_ADD; pavone@8: decoded->variant = VAR_IMMEDIATE; pavone@8: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@8: decoded->extra.size = size = (*istream >> 6) & 3; pavone@8: reg = *istream & 0x7; pavone@8: opmode = (*istream >> 3) & 0x7; pavone@8: switch (size) pavone@8: { pavone@8: case OPSIZE_BYTE: pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@8: break; pavone@8: case OPSIZE_WORD: pavone@15: decoded->src.params.immed = *(++istream); pavone@8: break; pavone@8: case OPSIZE_LONG: pavone@8: immed = *(++istream); pavone@15: decoded->src.params.immed = immed << 16 | *(++istream); pavone@8: break; pavone@5: } pavone@8: istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); pavone@823: if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@4: break; pavone@4: case 4: pavone@5: //BTST, BCHG, BCLR, BSET pavone@5: switch ((*istream >> 6) & 0x3) pavone@5: { pavone@5: case 0: pavone@5: decoded->op = M68K_BTST; pavone@5: break; pavone@5: case 1: pavone@5: decoded->op = M68K_BCHG; pavone@5: break; pavone@5: case 2: pavone@5: decoded->op = M68K_BCLR; pavone@5: break; pavone@5: case 3: pavone@5: decoded->op = M68K_BSET; pavone@5: break; pavone@5: } pavone@5: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@5: istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@4: break; pavone@4: case 5: pavone@5: //EORI, EORI to CCR, EORI to SR pavone@5: if ((*istream & 0xFF) == 0x3C) { pavone@5: decoded->op = M68K_EORI_CCR; pavone@5: decoded->extra.size = OPSIZE_BYTE; pavone@5: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@5: } else if((*istream & 0xFF) == 0x7C) { pavone@5: decoded->op = M68K_EORI_SR; pavone@5: decoded->extra.size = OPSIZE_WORD; pavone@5: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *(++istream); pavone@5: } else { pavone@8: decoded->op = M68K_EOR; pavone@8: decoded->variant = VAR_IMMEDIATE; pavone@8: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@8: decoded->extra.size = size = (*istream >> 6) & 3; pavone@8: reg = *istream & 0x7; pavone@8: opmode = (*istream >> 3) & 0x7; pavone@8: switch (size) pavone@8: { pavone@8: case OPSIZE_BYTE: pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@8: break; pavone@8: case OPSIZE_WORD: pavone@15: decoded->src.params.immed = *(++istream); pavone@8: break; pavone@8: case OPSIZE_LONG: pavone@8: immed = *(++istream); pavone@15: decoded->src.params.immed = immed << 16 | *(++istream); pavone@8: break; pavone@5: } pavone@8: istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); pavone@823: if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@5: } pavone@4: break; pavone@4: case 6: pavone@8: decoded->op = M68K_CMP; pavone@8: decoded->variant = VAR_IMMEDIATE; pavone@8: decoded->extra.size = (*istream >> 6) & 0x3; pavone@8: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@8: reg = *istream & 0x7; pavone@8: opmode = (*istream >> 3) & 0x7; pavone@8: switch (decoded->extra.size) pavone@8: { pavone@8: case OPSIZE_BYTE: pavone@15: decoded->src.params.immed = *(++istream) & 0xFF; pavone@8: break; pavone@8: case OPSIZE_WORD: pavone@15: decoded->src.params.immed = *(++istream); pavone@8: break; pavone@8: case OPSIZE_LONG: pavone@8: immed = *(++istream); pavone@15: decoded->src.params.immed = (immed << 16) | *(++istream); pavone@8: break; pavone@8: } pavone@630: istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); pavone@823: if (!istream || !m68k_valid_immed_dst(&(decoded->dst))) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@4: break; pavone@4: case 7: pavone@630: #ifdef M68010 pavone@630: decoded->op = M68K_MOVES; pavone@630: decoded->extra.size = *istream >> 6 & 0x3; pavone@630: immed = *(++istream); pavone@630: reg = immed >> 12 & 0x7; pavone@630: opmode = immed & 0x8000 ? MODE_AREG : MODE_REG; pavone@630: if (immed & 0x800) { pavone@642: decoded->src.addr_mode = opmode; pavone@642: decoded->src.params.regs.pri = reg; pavone@642: m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->dst)); pavone@642: } else { pavone@630: m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->src)); pavone@630: decoded->dst.addr_mode = opmode; pavone@630: decoded->dst.params.regs.pri = reg; pavone@630: } pavone@630: #endif pavone@4: break; pavone@4: } pavone@4: } pavone@0: break; pavone@0: case MOVE_BYTE: pavone@0: case MOVE_LONG: pavone@0: case MOVE_WORD: pavone@0: decoded->op = M68K_MOVE; pavone@0: decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG); pavone@18: opmode = (*istream >> 6) & 0x7; pavone@18: reg = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@18: istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); pavone@197: if (!istream || decoded->dst.addr_mode == MODE_IMMEDIATE) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@0: break; pavone@0: case MISC: pavone@518: pavone@2: if ((*istream & 0x1C0) == 0x1C0) { pavone@2: decoded->op = M68K_LEA; pavone@2: decoded->extra.size = OPSIZE_LONG; pavone@2: decoded->dst.addr_mode = MODE_AREG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@2: if (*istream & 0x100) { pavone@2: decoded->op = M68K_CHK; pavone@2: if ((*istream & 0x180) == 0x180) { pavone@2: decoded->extra.size = OPSIZE_WORD; pavone@2: } else { pavone@2: //only on M68020+ pavone@9: #ifdef M68020 pavone@2: decoded->extra.size = OPSIZE_LONG; pavone@9: #else pavone@9: decoded->op = M68K_INVALID; pavone@9: break; pavone@9: #endif pavone@2: } pavone@184: decoded->dst.addr_mode = MODE_REG; pavone@325: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@13: opmode = (*istream >> 3) & 0x7; pavone@61: if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG) { pavone@61: //TODO: Check for invalid modes that are dependent on direction pavone@9: decoded->op = M68K_MOVEM; pavone@9: decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; pavone@13: reg = *istream & 0x7; pavone@9: if(*istream & 0x400) { pavone@9: decoded->dst.addr_mode = MODE_REG; pavone@68: decoded->dst.params.immed = *(++istream); pavone@9: istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@412: if (decoded->src.addr_mode == MODE_PC_DISPLACE || decoded->src.addr_mode == MODE_PC_INDEX_DISP8) { pavone@412: //adjust displacement to account for extra instruction word pavone@412: decoded->src.params.regs.displacement += 2; pavone@412: } pavone@2: } else { pavone@9: decoded->src.addr_mode = MODE_REG; pavone@68: decoded->src.params.immed = *(++istream); pavone@9: istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } pavone@9: } else { pavone@9: optype = (*istream >> 9) & 0x7; pavone@9: size = (*istream >> 6) & 0x3; pavone@9: switch(optype) pavone@9: { pavone@9: case 0: pavone@9: //Move from SR or NEGX pavone@9: if (size == OPSIZE_INVALID) { pavone@9: decoded->op = M68K_MOVE_FROM_SR; pavone@9: size = OPSIZE_WORD; pavone@9: } else { pavone@9: decoded->op = M68K_NEGX; pavone@9: } pavone@9: decoded->extra.size = size; pavone@9: istream= m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: break; pavone@9: case 1: pavone@9: //MOVE from CCR or CLR pavone@2: if (size == OPSIZE_INVALID) { pavone@9: #ifdef M68010 pavone@9: decoded->op = M68K_MOVE_FROM_CCR; pavone@9: size = OPSIZE_WORD; pavone@9: #else pavone@630: break; pavone@9: #endif pavone@9: } else { pavone@9: decoded->op = M68K_CLR; pavone@9: } pavone@9: decoded->extra.size = size; pavone@9: istream= m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: break; pavone@9: case 2: pavone@9: //MOVE to CCR or NEG pavone@9: if (size == OPSIZE_INVALID) { pavone@9: decoded->op = M68K_MOVE_CCR; pavone@9: size = OPSIZE_WORD; pavone@9: istream= m68k_decode_op(istream, size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } else { pavone@9: decoded->op = M68K_NEG; pavone@9: istream= m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } pavone@9: decoded->extra.size = size; pavone@9: break; pavone@9: case 3: pavone@9: //MOVE to SR or NOT pavone@9: if (size == OPSIZE_INVALID) { pavone@9: decoded->op = M68K_MOVE_SR; pavone@9: size = OPSIZE_WORD; pavone@9: istream= m68k_decode_op(istream, size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@9: decoded->op = M68K_NOT; pavone@9: istream= m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@9: decoded->extra.size = size; pavone@9: break; pavone@9: case 4: pavone@9: //EXT, EXTB, LINK.l, NBCD, SWAP, BKPT, PEA pavone@9: switch((*istream >> 3) & 0x3F) pavone@2: { pavone@2: case 1: pavone@9: #ifdef M68020 pavone@9: decoded->op = M68K_LINK; pavone@9: decoded->extra.size = OPSIZE_LONG; pavone@9: reg = *istream & 0x7; pavone@9: immed = *(++istream) << 16; pavone@9: immed |= *(++istream); pavone@9: #endif pavone@9: break; pavone@9: case 8: pavone@9: decoded->op = M68K_SWAP; pavone@9: decoded->src.addr_mode = MODE_REG; pavone@9: decoded->src.params.regs.pri = *istream & 0x7; pavone@9: decoded->extra.size = OPSIZE_WORD; pavone@2: break; pavone@9: case 9: pavone@9: #ifdef M68010 pavone@9: decoded->op = M68K_BKPT; pavone@9: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@10: decoded->extra.size = OPSIZE_UNSIZED; pavone@15: decoded->src.params.immed = *istream & 0x7; pavone@9: #endif pavone@9: break; pavone@9: case 0x10: pavone@9: decoded->op = M68K_EXT; pavone@93: decoded->dst.addr_mode = MODE_REG; pavone@93: decoded->dst.params.regs.pri = *istream & 0x7; pavone@9: decoded->extra.size = OPSIZE_WORD; pavone@9: break; pavone@9: case 0x18: pavone@9: decoded->op = M68K_EXT; pavone@93: decoded->dst.addr_mode = MODE_REG; pavone@93: decoded->dst.params.regs.pri = *istream & 0x7; pavone@9: decoded->extra.size = OPSIZE_LONG; pavone@9: break; pavone@9: case 0x38: pavone@9: #ifdef M68020 pavone@9: #endif pavone@2: break; pavone@9: default: pavone@9: if (!(*istream & 0x1C0)) { pavone@9: decoded->op = M68K_NBCD; pavone@9: decoded->extra.size = OPSIZE_BYTE; pavone@9: istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@13: } else if((*istream & 0x1C0) == 0x40) { pavone@9: decoded->op = M68K_PEA; pavone@9: decoded->extra.size = OPSIZE_LONG; pavone@116: istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } pavone@9: } pavone@9: break; pavone@9: case 5: pavone@9: //BGND, ILLEGAL, TAS, TST pavone@9: optype = *istream & 0xFF; pavone@9: if (optype == 0xFA) { pavone@9: //BGND - CPU32 only pavone@9: } else if (optype == 0xFC) { pavone@9: decoded->op = M68K_ILLEGAL; pavone@10: decoded->extra.size = OPSIZE_UNSIZED; pavone@9: } else { pavone@9: if (size == OPSIZE_INVALID) { pavone@9: decoded->op = M68K_TAS; pavone@835: decoded->extra.size = OPSIZE_BYTE; pavone@835: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); pavone@835: if (!istream) { pavone@835: decoded->op = M68K_INVALID; pavone@835: break; pavone@835: } pavone@9: } else { pavone@9: decoded->op = M68K_TST; pavone@9: decoded->extra.size = size; pavone@9: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } pavone@9: } pavone@518: break; pavone@9: case 6: pavone@9: //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL pavone@9: #ifdef M68020 pavone@9: //TODO: Implement these for 68020+ support pavone@9: #endif pavone@9: break; pavone@9: case 7: pavone@9: //TRAP, LINK.w, UNLNK, MOVE USP, RESET, NOP, STOP, RTE, RTD, RTS, TRAPV, RTR, MOVEC, JSR, JMP pavone@9: if (*istream & 0x80) { pavone@9: //JSR, JMP pavone@9: if (*istream & 0x40) { pavone@9: decoded->op = M68K_JMP; pavone@9: } else { pavone@9: decoded->op = M68K_JSR; pavone@9: } pavone@10: decoded->extra.size = OPSIZE_UNSIZED; pavone@10: istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } else { pavone@9: //it would appear bit 6 needs to be set for it to be a valid instruction here pavone@9: switch((*istream >> 3) & 0x7) pavone@2: { pavone@2: case 0: pavone@2: case 1: pavone@9: //TRAP pavone@9: decoded->op = M68K_TRAP; pavone@10: decoded->extra.size = OPSIZE_UNSIZED; pavone@9: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = *istream & 0xF; pavone@2: break; pavone@2: case 2: pavone@9: //LINK.w pavone@9: decoded->op = M68K_LINK; pavone@2: decoded->extra.size = OPSIZE_WORD; pavone@9: decoded->src.addr_mode = MODE_AREG; pavone@9: decoded->src.params.regs.pri = *istream & 0x7; pavone@9: decoded->dst.addr_mode = MODE_IMMEDIATE; pavone@93: decoded->dst.params.immed = sign_extend16(*(++istream)); pavone@2: break; pavone@2: case 3: pavone@9: //UNLK pavone@9: decoded->op = M68K_UNLK; pavone@10: decoded->extra.size = OPSIZE_UNSIZED; pavone@9: decoded->dst.addr_mode = MODE_AREG; pavone@9: decoded->dst.params.regs.pri = *istream & 0x7; pavone@2: break; pavone@2: case 4: pavone@2: case 5: pavone@9: //MOVE USP pavone@9: decoded->op = M68K_MOVE_USP; pavone@9: if (*istream & 0x8) { pavone@9: decoded->dst.addr_mode = MODE_AREG; pavone@9: decoded->dst.params.regs.pri = *istream & 0x7; pavone@9: } else { pavone@9: decoded->src.addr_mode = MODE_AREG; pavone@9: decoded->src.params.regs.pri = *istream & 0x7; pavone@9: } pavone@2: break; pavone@2: case 6: pavone@10: decoded->extra.size = OPSIZE_UNSIZED; pavone@9: switch(*istream & 0x7) pavone@9: { pavone@9: case 0: pavone@9: decoded->op = M68K_RESET; pavone@9: break; pavone@9: case 1: pavone@9: decoded->op = M68K_NOP; pavone@9: break; pavone@9: case 2: pavone@9: decoded->op = M68K_STOP; pavone@9: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed =*(++istream); pavone@9: break; pavone@9: case 3: pavone@9: decoded->op = M68K_RTE; pavone@9: break; pavone@9: case 4: pavone@9: #ifdef M68010 pavone@9: decoded->op = M68K_RTD; pavone@9: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed =*(++istream); pavone@9: #endif pavone@9: break; pavone@9: case 5: pavone@9: decoded->op = M68K_RTS; pavone@9: break; pavone@9: case 6: pavone@9: decoded->op = M68K_TRAPV; pavone@9: break; pavone@9: case 7: pavone@9: decoded->op = M68K_RTR; pavone@9: break; pavone@9: } pavone@2: break; pavone@2: case 7: pavone@9: //MOVEC pavone@9: #ifdef M68010 pavone@630: decoded->op = M68K_MOVEC; pavone@630: immed = *(++istream); pavone@630: reg = immed >> 12 & 0x7; pavone@630: opmode = immed & 0x8000 ? MODE_AREG : MODE_REG; pavone@641: immed &= 0xFFF; pavone@630: if (immed & 0x800) { pavone@630: if (immed > MAX_HIGH_CR) { pavone@630: decoded->op = M68K_INVALID; pavone@630: break; pavone@630: } else { pavone@630: immed = immed - 0x800 + CR_USP; pavone@630: } pavone@630: } else { pavone@630: if (immed > MAX_LOW_CR) { pavone@630: decoded->op = M68K_INVALID; pavone@630: break; pavone@630: } pavone@630: } pavone@630: if (*start & 1) { pavone@630: decoded->src.addr_mode = opmode; pavone@630: decoded->src.params.regs.pri = reg; pavone@630: decoded->dst.params.immed = immed; pavone@630: } else { pavone@630: decoded->dst.addr_mode = opmode; pavone@630: decoded->dst.params.regs.pri = reg; pavone@630: decoded->src.params.immed = immed; pavone@630: } pavone@9: #endif pavone@2: break; pavone@2: } pavone@2: } pavone@9: break; pavone@2: } pavone@2: } pavone@2: } pavone@2: } pavone@0: break; pavone@0: case QUICK_ARITH_LOOP: pavone@0: size = (*istream >> 6) & 3; pavone@0: if (size == 0x3) { pavone@0: //DBcc, TRAPcc or Scc pavone@2: m68k_decode_cond(*istream, decoded); pavone@111: if (((*istream >> 3) & 0x7) == 1) { pavone@0: decoded->op = M68K_DBCC; pavone@2: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@0: decoded->dst.addr_mode = MODE_REG; pavone@2: decoded->dst.params.regs.pri = *istream & 0x7; pavone@46: decoded->src.params.immed = sign_extend16(*(++istream)); pavone@111: } else if(((*istream >> 3) & 0x7) == 1 && (*istream & 0x7) > 1 && (*istream & 0x7) < 5) { pavone@2: #ifdef M68020 pavone@0: decoded->op = M68K_TRAPCC; pavone@2: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@0: //TODO: Figure out what to do with OPMODE and optional extention words pavone@2: #endif pavone@111: } else { pavone@0: decoded->op = M68K_SCC; pavone@111: decoded->extra.cond = (*istream >> 8) & 0xF; pavone@2: istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@0: } pavone@0: } else { pavone@0: //ADDQ, SUBQ pavone@0: decoded->variant = VAR_QUICK; pavone@0: decoded->extra.size = size; pavone@2: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@91: immed = m68k_reg_quick_field(*istream); pavone@0: if (!immed) { pavone@0: immed = 8; pavone@0: } pavone@15: decoded->src.params.immed = immed; pavone@2: if (*istream & 0x100) { pavone@0: decoded->op = M68K_SUB; pavone@0: } else { pavone@0: decoded->op = M68K_ADD; pavone@0: } pavone@94: istream = m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@0: } pavone@0: break; pavone@2: case BRANCH: pavone@2: m68k_decode_cond(*istream, decoded); pavone@2: decoded->op = decoded->extra.cond == COND_FALSE ? M68K_BSR : M68K_BCC; pavone@2: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@2: immed = *istream & 0xFF; pavone@2: if (immed == 0) { pavone@2: decoded->variant = VAR_WORD; pavone@2: immed = *(++istream); pavone@2: immed = sign_extend16(immed); pavone@154: #ifdef M68020 pavone@2: } else if (immed == 0xFF) { pavone@2: decoded->variant = VAR_LONG; pavone@2: immed = *(++istream) << 16; pavone@2: immed |= *(++istream); pavone@154: #endif pavone@2: } else { pavone@2: decoded->variant = VAR_BYTE; pavone@2: immed = sign_extend8(immed); pavone@2: } pavone@15: decoded->src.params.immed = immed; pavone@2: break; pavone@2: case MOVEQ: pavone@208: if (*istream & 0x100) { pavone@208: decoded->op = M68K_INVALID; pavone@630: break; pavone@208: } pavone@2: decoded->op = M68K_MOVE; pavone@2: decoded->variant = VAR_QUICK; pavone@15: decoded->extra.size = OPSIZE_LONG; pavone@2: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@15: decoded->src.params.immed = sign_extend8(*istream & 0xFF); pavone@2: decoded->dst.addr_mode = MODE_REG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: immed = *istream & 0xFF; pavone@2: break; pavone@2: case OR_DIV_SBCD: pavone@11: //for OR, if opmode bit 2 is 1, then src = Dn, dst = pavone@11: opmode = (*istream >> 6) & 0x7; pavone@11: size = opmode & 0x3; pavone@11: if (size == OPSIZE_INVALID || (opmode & 0x4 && !(*istream & 0x30))) { pavone@11: switch(opmode) pavone@11: { pavone@11: case 3: pavone@11: decoded->op = M68K_DIVU; pavone@11: decoded->extra.size = OPSIZE_WORD; pavone@11: decoded->dst.addr_mode = MODE_REG; pavone@11: decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; pavone@11: istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); pavone@183: if (!istream || decoded->src.addr_mode == MODE_AREG) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@11: break; pavone@11: case 4: pavone@11: decoded->op = M68K_SBCD; pavone@613: decoded->extra.size = OPSIZE_BYTE; pavone@11: decoded->dst.addr_mode = decoded->src.addr_mode = *istream & 0x8 ? MODE_AREG_PREDEC : MODE_REG; pavone@11: decoded->src.params.regs.pri = *istream & 0x7; pavone@11: decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; pavone@11: break; pavone@11: case 5: pavone@11: #ifdef M68020 pavone@11: #endif pavone@11: break; pavone@11: case 6: pavone@11: #ifdef M68020 pavone@11: #endif pavone@11: break; pavone@11: case 7: pavone@11: decoded->op = M68K_DIVS; pavone@11: decoded->extra.size = OPSIZE_WORD; pavone@11: decoded->dst.addr_mode = MODE_REG; pavone@11: decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; pavone@11: istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); pavone@183: if (!istream || decoded->src.addr_mode == MODE_AREG) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@518: break; pavone@11: } pavone@11: } else { pavone@11: decoded->op = M68K_OR; pavone@11: decoded->extra.size = size; pavone@11: if (opmode & 0x4) { pavone@11: decoded->src.addr_mode = MODE_REG; pavone@11: decoded->src.params.regs.pri = (*istream >> 9) & 0x7; pavone@11: istream = m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@11: } else { pavone@11: decoded->dst.addr_mode = MODE_REG; pavone@11: decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; pavone@11: istream = m68k_decode_op(istream, size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@11: } pavone@11: } pavone@2: break; pavone@2: case SUB_SUBX: pavone@101: size = (*istream >> 6) & 0x3; pavone@2: decoded->op = M68K_SUB; pavone@2: if (*istream & 0x100) { pavone@2: // destination, SUBA.l or SUBX pavone@101: if (*istream & 0x30 || size == OPSIZE_INVALID) { pavone@2: if (size == OPSIZE_INVALID) { pavone@2: //SUBA.l pavone@2: decoded->extra.size = OPSIZE_LONG; pavone@2: decoded->dst.addr_mode = MODE_AREG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@2: decoded->extra.size = size; pavone@2: decoded->src.addr_mode = MODE_REG; pavone@18: decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: } else { pavone@2: //SUBX pavone@2: decoded->op = M68K_SUBX; pavone@2: decoded->extra.size = size; pavone@184: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@184: decoded->src.params.regs.pri = *istream & 0x7; pavone@184: if (*istream & 0x8) { pavone@184: decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC; pavone@184: } else { pavone@184: decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG; pavone@176: } pavone@2: } pavone@2: } else { pavone@2: if (size == OPSIZE_INVALID) { pavone@2: //SUBA.w pavone@2: decoded->extra.size = OPSIZE_WORD; pavone@2: decoded->dst.addr_mode = MODE_AREG; pavone@2: } else { pavone@2: decoded->extra.size = size; pavone@2: decoded->dst.addr_mode = MODE_REG; pavone@2: } pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: break; pavone@2: case RESERVED: pavone@2: break; pavone@2: case CMP_XOR: pavone@120: size = (*istream >> 6) & 0x3; pavone@2: decoded->op = M68K_CMP; pavone@2: if (*istream & 0x100) { pavone@120: //CMPM or CMPA.l or EOR pavone@120: if (size == OPSIZE_INVALID) { pavone@120: decoded->extra.size = OPSIZE_LONG; pavone@120: decoded->dst.addr_mode = MODE_AREG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@136: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@184: reg = m68k_reg_quick_field(*istream); pavone@120: istream = m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@181: decoded->extra.size = size; pavone@181: if (decoded->dst.addr_mode == MODE_AREG) { pavone@120: //CMPM pavone@120: decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; pavone@120: decoded->src.params.regs.pri = decoded->dst.params.regs.pri; pavone@184: decoded->dst.params.regs.pri = reg; pavone@120: } else { pavone@120: //EOR pavone@120: decoded->op = M68K_EOR; pavone@120: decoded->src.addr_mode = MODE_REG; pavone@184: decoded->src.params.regs.pri = reg; pavone@120: } pavone@2: } pavone@2: } else { pavone@120: //CMP or CMPA.w pavone@120: if (size == OPSIZE_INVALID) { pavone@120: decoded->extra.size = OPSIZE_WORD; pavone@120: decoded->dst.addr_mode = MODE_AREG; pavone@120: } else { pavone@120: decoded->extra.size = size; pavone@120: decoded->dst.addr_mode = MODE_REG; pavone@120: } pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@136: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: break; pavone@2: case AND_MUL_ABCD_EXG: pavone@2: //page 575 for summary pavone@2: //EXG opmodes: pavone@2: //01000 -data regs pavone@2: //01001 -addr regs pavone@2: //10001 -one of each pavone@2: //AND opmodes: pavone@2: //operand order bit + 2 size bits (00 - 10) pavone@2: //no address register direct addressing pavone@2: //data register direct not allowed when is the source (operand order bit of 1) pavone@2: if (*istream & 0x100) { pavone@2: if ((*istream & 0xC0) == 0xC0) { pavone@2: decoded->op = M68K_MULS; pavone@2: decoded->extra.size = OPSIZE_WORD; pavone@3: decoded->dst.addr_mode = MODE_REG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else if(!(*istream & 0xF0)) { pavone@2: decoded->op = M68K_ABCD; pavone@3: decoded->extra.size = OPSIZE_BYTE; pavone@3: decoded->src.params.regs.pri = *istream & 0x7; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@3: decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG; pavone@2: } else if(!(*istream & 0x30)) { pavone@2: decoded->op = M68K_EXG; pavone@2: decoded->extra.size = OPSIZE_LONG; pavone@18: decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: decoded->dst.params.regs.pri = *istream & 0x7; pavone@2: if (*istream & 0x8) { pavone@2: if (*istream & 0x80) { pavone@2: decoded->src.addr_mode = MODE_REG; pavone@2: decoded->dst.addr_mode = MODE_AREG; pavone@2: } else { pavone@2: decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG; pavone@2: } pavone@2: } else { pavone@2: decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG; pavone@2: } pavone@2: } else { pavone@2: decoded->op = M68K_AND; pavone@90: decoded->extra.size = (*istream >> 6) & 0x3; pavone@60: decoded->src.addr_mode = MODE_REG; pavone@60: decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); pavone@60: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: } else { pavone@2: if ((*istream & 0xC0) == 0xC0) { pavone@2: decoded->op = M68K_MULU; pavone@2: decoded->extra.size = OPSIZE_WORD; pavone@3: decoded->dst.addr_mode = MODE_REG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@2: decoded->op = M68K_AND; pavone@90: decoded->extra.size = (*istream >> 6) & 0x3; pavone@60: decoded->dst.addr_mode = MODE_REG; pavone@60: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@60: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: } pavone@2: break; pavone@2: case ADD_ADDX: pavone@101: size = (*istream >> 6) & 0x3; pavone@2: decoded->op = M68K_ADD; pavone@2: if (*istream & 0x100) { pavone@2: // destination, ADDA.l or ADDX pavone@101: if (*istream & 0x30 || size == OPSIZE_INVALID) { pavone@2: if (size == OPSIZE_INVALID) { pavone@2: //ADDA.l pavone@2: decoded->extra.size = OPSIZE_LONG; pavone@2: decoded->dst.addr_mode = MODE_AREG; pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } else { pavone@2: decoded->extra.size = size; pavone@2: decoded->src.addr_mode = MODE_REG; pavone@18: decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, size, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: } else { pavone@2: //ADDX pavone@2: decoded->op = M68K_ADDX; pavone@2: decoded->extra.size = size; pavone@184: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@184: decoded->src.params.regs.pri = *istream & 0x7; pavone@184: if (*istream & 0x8) { pavone@184: decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC; pavone@184: } else { pavone@184: decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG; pavone@176: } pavone@2: } pavone@2: } else { pavone@2: if (size == OPSIZE_INVALID) { pavone@2: //ADDA.w pavone@2: decoded->extra.size = OPSIZE_WORD; pavone@2: decoded->dst.addr_mode = MODE_AREG; pavone@2: } else { pavone@2: decoded->extra.size = size; pavone@2: decoded->dst.addr_mode = MODE_REG; pavone@2: } pavone@18: decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); pavone@2: istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@2: } pavone@2: break; pavone@2: case SHIFT_ROTATE: pavone@9: if ((*istream & 0x8C0) == 0xC0) { pavone@9: switch((*istream >> 8) & 0x7) pavone@9: { pavone@9: case 0: pavone@9: decoded->op = M68K_ASR; pavone@9: break; pavone@9: case 1: pavone@9: decoded->op = M68K_ASL; pavone@9: break; pavone@9: case 2: pavone@9: decoded->op = M68K_LSR; pavone@9: break; pavone@9: case 3: pavone@9: decoded->op = M68K_LSL; pavone@9: break; pavone@9: case 4: pavone@9: decoded->op = M68K_ROXR; pavone@9: break; pavone@9: case 5: pavone@9: decoded->op = M68K_ROXL; pavone@9: break; pavone@9: case 6: pavone@9: decoded->op = M68K_ROR; pavone@9: break; pavone@9: case 7: pavone@9: decoded->op = M68K_ROL; pavone@9: break; pavone@9: } pavone@9: decoded->extra.size = OPSIZE_WORD; pavone@9: istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); pavone@176: if (!istream) { pavone@176: decoded->op = M68K_INVALID; pavone@630: break; pavone@176: } pavone@9: } else if((*istream & 0xC0) != 0xC0) { pavone@9: switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) pavone@9: { pavone@9: case 0: pavone@9: decoded->op = M68K_ASR; pavone@9: break; pavone@9: case 1: pavone@9: decoded->op = M68K_ASL; pavone@9: break; pavone@9: case 2: pavone@9: decoded->op = M68K_LSR; pavone@9: break; pavone@9: case 3: pavone@9: decoded->op = M68K_LSL; pavone@9: break; pavone@9: case 4: pavone@9: decoded->op = M68K_ROXR; pavone@9: break; pavone@9: case 5: pavone@9: decoded->op = M68K_ROXL; pavone@9: break; pavone@9: case 6: pavone@9: decoded->op = M68K_ROR; pavone@9: break; pavone@9: case 7: pavone@9: decoded->op = M68K_ROL; pavone@9: break; pavone@9: } pavone@9: decoded->extra.size = (*istream >> 6) & 0x3; pavone@9: immed = (*istream >> 9) & 0x7; pavone@51: if (*istream & 0x20) { pavone@9: decoded->src.addr_mode = MODE_REG; pavone@9: decoded->src.params.regs.pri = immed; pavone@50: } else { pavone@50: decoded->src.addr_mode = MODE_IMMEDIATE; pavone@50: if (!immed) { pavone@50: immed = 8; pavone@50: } pavone@50: decoded->src.params.immed = immed; pavone@9: } pavone@9: decoded->dst.addr_mode = MODE_REG; pavone@9: decoded->dst.params.regs.pri = *istream & 0x7; pavone@518: pavone@9: } else { pavone@9: #ifdef M68020 pavone@9: //TODO: Implement bitfield instructions for M68020+ support pavone@636: switch (*istream >> 8 & 7) pavone@636: { pavone@636: case 0: pavone@636: decoded->op = M68K_BFTST; // pavone@636: break; pavone@636: case 1: pavone@636: decoded->op = M68K_BFEXTU; //, Dn pavone@636: break; pavone@636: case 2: pavone@636: decoded->op = M68K_BFCHG; // pavone@636: break; pavone@636: case 3: pavone@636: decoded->op = M68K_BFEXTS; //, Dn pavone@636: break; pavone@636: case 4: pavone@636: decoded->op = M68K_BFCLR; // pavone@636: break; pavone@636: case 5: pavone@636: decoded->op = M68K_BFFFO; //, Dn pavone@636: break; pavone@636: case 6: pavone@636: decoded->op = M68K_BFSET; // pavone@636: break; pavone@636: case 7: pavone@636: decoded->op = M68K_BFINS; //Dn, pavone@636: break; pavone@636: } pavone@636: opmode = *istream >> 3 & 0x7; pavone@636: reg = *istream & 0x7; pavone@636: m68k_op_info *ea, *other; pavone@636: if (decoded->op == M68K_BFEXTU || decoded->op == M68K_BFEXTS || decoded->op == M68K_BFFFO) pavone@636: { pavone@636: ea = &(decoded->src); pavone@636: other = &(decoded->dst); pavone@636: } else { pavone@636: ea = &(decoded->dst); pavone@636: other = &(decoded->dst); pavone@636: } pavone@636: if (*istream & 0x100) pavone@636: { pavone@636: immed = *(istream++); pavone@636: other->addr_mode = MODE_REG; pavone@636: other->params.regs.pri = immed >> 12 & 0x7; pavone@636: } else { pavone@636: immed = *(istream++); pavone@636: } pavone@636: decoded->extra.size = OPSIZE_UNSIZED; pavone@636: istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, ea); pavone@636: ea->addr_mode |= M68K_FLAG_BITFIELD; pavone@636: ea->bitfield = immed & 0xFFF; pavone@9: #endif pavone@9: } pavone@2: break; pavone@2: case COPROC: pavone@2: //TODO: Implement me pavone@2: break; pavone@2: } pavone@630: if (decoded->op == M68K_INVALID) { pavone@630: decoded->src.params.immed = *start; pavone@981: decoded->bytes = 2; pavone@630: return start + 1; pavone@630: } pavone@981: decoded->bytes = 2 * (istream + 1 - start); pavone@2: return istream+1; pavone@2: } pavone@2: pavone@518: uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs) pavone@518: { pavone@518: if(inst->op == M68K_BCC || inst->op == M68K_BSR || inst->op == M68K_DBCC) { pavone@518: return inst->address + 2 + inst->src.params.immed; pavone@518: } else if(inst->op == M68K_JMP || inst->op == M68K_JSR) { pavone@518: uint32_t ret = 0; pavone@518: switch(inst->src.addr_mode) pavone@518: { pavone@518: case MODE_AREG_INDIRECT: pavone@518: ret = aregs[inst->src.params.regs.pri]; pavone@518: break; pavone@518: case MODE_AREG_INDEX_DISP8: { pavone@518: uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7; pavone@518: ret = aregs[inst->src.params.regs.pri]; pavone@518: uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs; pavone@518: if (inst->src.params.regs.sec & 1) { pavone@518: //32-bit index register pavone@518: ret += regfile[sec_reg]; pavone@518: } else { pavone@518: //16-bit index register pavone@518: if (regfile[sec_reg] & 0x8000) { pavone@518: ret += (0xFFFF0000 | regfile[sec_reg]); pavone@518: } else { pavone@518: ret += regfile[sec_reg]; pavone@518: } pavone@518: } pavone@518: ret += inst->src.params.regs.displacement; pavone@518: break; pavone@518: } pavone@518: case MODE_PC_DISPLACE: pavone@518: ret = inst->src.params.regs.displacement + inst->address + 2; pavone@518: break; pavone@518: case MODE_PC_INDEX_DISP8: { pavone@518: uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7; pavone@518: ret = inst->address + 2; pavone@518: uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs; pavone@518: if (inst->src.params.regs.sec & 1) { pavone@518: //32-bit index register pavone@518: ret += regfile[sec_reg]; pavone@518: } else { pavone@518: //16-bit index register pavone@518: if (regfile[sec_reg] & 0x8000) { pavone@518: ret += (0xFFFF0000 | regfile[sec_reg]); pavone@518: } else { pavone@518: ret += regfile[sec_reg]; pavone@518: } pavone@518: } pavone@518: ret += inst->src.params.regs.displacement; pavone@518: break; pavone@518: } pavone@518: case MODE_ABSOLUTE: pavone@518: case MODE_ABSOLUTE_SHORT: pavone@518: ret = inst->src.params.immed; pavone@518: break; pavone@518: } pavone@518: return ret; pavone@518: } pavone@518: return 0; pavone@518: } pavone@518: pavone@518: uint8_t m68k_is_branch(m68kinst * inst) pavone@518: { pavone@518: return (inst->op == M68K_BCC && inst->extra.cond != COND_FALSE) pavone@518: || (inst->op == M68K_DBCC && inst->extra.cond != COND_TRUE) pavone@518: || inst->op == M68K_BSR || inst->op == M68K_JMP || inst->op == M68K_JSR; pavone@518: } pavone@518: pavone@518: uint8_t m68k_is_noncall_branch(m68kinst * inst) pavone@518: { pavone@518: return m68k_is_branch(inst) && inst->op != M68K_BSR && inst->op != M68K_JSR; pavone@518: } pavone@518: pavone@518: pavone@2: char * mnemonics[] = { pavone@2: "abcd", pavone@2: "add", pavone@2: "addx", pavone@2: "and", pavone@13: "andi",//ccr pavone@13: "andi",//sr pavone@2: "asl", pavone@2: "asr", pavone@2: "bcc", pavone@2: "bchg", pavone@2: "bclr", pavone@2: "bset", pavone@2: "bsr", pavone@2: "btst", pavone@2: "chk", pavone@2: "clr", pavone@2: "cmp", pavone@2: "dbcc", pavone@2: "divs", pavone@2: "divu", pavone@2: "eor", pavone@13: "eori",//ccr pavone@13: "eori",//sr pavone@2: "exg", pavone@2: "ext", pavone@2: "illegal", pavone@2: "jmp", pavone@2: "jsr", pavone@2: "lea", pavone@2: "link", pavone@2: "lsl", pavone@2: "lsr", pavone@2: "move", pavone@13: "move",//ccr pavone@13: "move",//from_sr pavone@13: "move",//sr pavone@50: "move",//usp pavone@2: "movem", pavone@2: "movep", pavone@2: "muls", pavone@2: "mulu", pavone@2: "nbcd", pavone@2: "neg", pavone@2: "negx", pavone@2: "nop", pavone@2: "not", pavone@2: "or", pavone@13: "ori",//ccr pavone@13: "ori",//sr pavone@2: "pea", pavone@2: "reset", pavone@2: "rol", pavone@2: "ror", pavone@2: "roxl", pavone@2: "roxr", pavone@2: "rte", pavone@2: "rtr", pavone@2: "rts", pavone@2: "sbcd", pavone@2: "scc", pavone@2: "stop", pavone@2: "sub", pavone@2: "subx", pavone@2: "swap", pavone@2: "tas", pavone@2: "trap", pavone@2: "trapv", pavone@2: "tst", pavone@12: "unlk", pavone@630: "invalid", pavone@630: #ifdef M68010 pavone@630: "bkpt", pavone@630: "move", //from ccr pavone@630: "movec", pavone@630: "moves", pavone@636: "rtd", pavone@630: #endif pavone@630: #ifdef M68020 pavone@630: "bfchg", pavone@630: "bfclr", pavone@630: "bfexts", pavone@630: "bfextu", pavone@630: "bfffo", pavone@630: "bfins", pavone@630: "bfset", pavone@630: "bftst", pavone@630: "callm", pavone@630: "cas", pavone@630: "cas2", pavone@630: "chk2", pavone@630: "cmp2", pavone@630: "cpbcc", pavone@630: "cpdbcc", pavone@630: "cpgen", pavone@630: "cprestore", pavone@630: "cpsave", pavone@630: "cpscc", pavone@630: "cptrapcc", pavone@630: "divsl", pavone@630: "divul", pavone@630: "extb", pavone@630: "pack", pavone@630: "rtm", pavone@630: "trapcc", pavone@630: "unpk" pavone@630: #endif pavone@2: }; pavone@2: pavone@2: char * cond_mnem[] = { pavone@2: "ra", pavone@2: "f", pavone@2: "hi", pavone@2: "ls", pavone@2: "cc", pavone@2: "cs", pavone@2: "ne", pavone@2: "eq", pavone@2: "vc", pavone@2: "vs", pavone@2: "pl", pavone@2: "mi", pavone@2: "ge", pavone@2: "lt", pavone@2: "gt", pavone@2: "le" pavone@2: }; pavone@630: #ifdef M68010 pavone@630: char * cr_mnem[] = { pavone@630: "SFC", pavone@630: "DFC", pavone@630: #ifdef M68020 pavone@630: "CACR", pavone@630: #endif pavone@630: "USP", pavone@630: "VBR", pavone@630: #ifdef M68020 pavone@630: "CAAR", pavone@630: "MSP", pavone@630: "ISP" pavone@630: #endif pavone@630: }; pavone@630: #endif pavone@2: pavone@634: int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data) pavone@2: { pavone@2: char * c = need_comma ? "," : ""; pavone@636: int ret = 0; pavone@636: #ifdef M68020 pavone@636: uint8_t addr_mode = decoded->addr_mode & (~M68K_FLAG_BITFIELD); pavone@636: #else pavone@636: uint8_t addr_mode = decoded->addr_mode; pavone@636: #endif pavone@636: switch(addr_mode) pavone@2: { pavone@2: case MODE_REG: pavone@636: ret = sprintf(dst, "%s d%d", c, decoded->params.regs.pri); pavone@636: break; pavone@2: case MODE_AREG: pavone@636: ret = sprintf(dst, "%s a%d", c, decoded->params.regs.pri); pavone@636: break; pavone@2: case MODE_AREG_INDIRECT: pavone@636: ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri); pavone@636: break; pavone@2: case MODE_AREG_POSTINC: pavone@636: ret = sprintf(dst, "%s (a%d)+", c, decoded->params.regs.pri); pavone@636: break; pavone@2: case MODE_AREG_PREDEC: pavone@636: ret = sprintf(dst, "%s -(a%d)", c, decoded->params.regs.pri); pavone@636: break; pavone@13: case MODE_AREG_DISPLACE: pavone@636: ret = sprintf(dst, "%s (%d, a%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri); pavone@636: break; pavone@79: case MODE_AREG_INDEX_DISP8: pavone@638: #ifdef M68020 pavone@638: if (decoded->params.regs.scale) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } else { pavone@638: #endif pavone@638: ret = sprintf(dst, "%s (%d, a%d, %c%d.%c)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w'); pavone@638: #ifdef M68020 pavone@638: } pavone@638: #endif pavone@638: break; pavone@638: #ifdef M68020 pavone@638: case MODE_AREG_INDEX_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s (a%d, %c%d.%c*%d)", c, decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } pavone@638: break; pavone@638: case MODE_AREG_PREINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d])", c, decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_AREG_POSTINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d)", c, decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri, pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_AREG_MEM_INDIRECT: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([a%d])", c, decoded->params.regs.pri); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, a%d])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([a%d], %d.%c)", c, decoded->params.regs.pri, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, a%d], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@636: break; pavone@638: case MODE_AREG_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, a%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri); pavone@638: } else { pavone@638: //this is a lossy representation of the encoded instruction pavone@638: //not sure if there's a better way to print it though pavone@638: ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri); pavone@638: } pavone@638: break; pavone@638: case MODE_INDEX_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s (%c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: } pavone@638: break; pavone@638: case MODE_PREINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([%c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([%c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_POSTINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_MEM_INDIRECT: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([])", c); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([], %d.%c)", c, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l'); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s ()", c); pavone@638: } pavone@638: break; pavone@638: #endif pavone@2: case MODE_IMMEDIATE: pavone@61: case MODE_IMMEDIATE_WORD: pavone@636: ret = sprintf(dst, (decoded->params.immed <= 128 ? "%s #%d" : "%s #$%X"), c, decoded->params.immed); pavone@636: break; pavone@13: case MODE_ABSOLUTE_SHORT: pavone@638: if (labels) { pavone@636: ret = sprintf(dst, "%s ", c); pavone@634: ret += label_fun(dst+ret, decoded->params.immed, data); pavone@634: strcat(dst+ret, ".w"); pavone@636: ret = ret + 2; pavone@134: } else { pavone@636: ret = sprintf(dst, "%s $%X.w", c, decoded->params.immed); pavone@134: } pavone@636: break; pavone@13: case MODE_ABSOLUTE: pavone@134: if (labels) { pavone@636: ret = sprintf(dst, "%s ", c); pavone@634: ret += label_fun(dst+ret, decoded->params.immed, data); pavone@634: strcat(dst+ret, ".l"); pavone@636: ret = ret + 2; pavone@134: } else { pavone@636: ret = sprintf(dst, "%s $%X", c, decoded->params.immed); pavone@134: } pavone@636: break; pavone@13: case MODE_PC_DISPLACE: pavone@134: if (labels) { pavone@636: ret = sprintf(dst, "%s ", c); pavone@634: ret += label_fun(dst+ret, address + 2 + decoded->params.regs.displacement, data); pavone@634: strcat(dst+ret, "(pc)"); pavone@636: ret = ret + 4; pavone@134: } else { pavone@636: ret = sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement); pavone@134: } pavone@636: break; pavone@79: case MODE_PC_INDEX_DISP8: pavone@638: #ifdef M68020 pavone@638: if (decoded->params.regs.scale) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } else { pavone@638: #endif pavone@638: ret = sprintf(dst, "%s (%d, pc, %c%d.%c)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w'); pavone@638: #ifdef M68020 pavone@638: } pavone@638: #endif pavone@638: break; pavone@638: #ifdef M68020 pavone@638: case MODE_PC_INDEX_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s (pc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: } pavone@638: break; pavone@638: case MODE_PC_PREINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([pc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([pc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_PC_POSTINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([pc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([pc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_PC_MEM_INDIRECT: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([pc])", c); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, pc])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([pc], %d.%c)", c, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, pc], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_PC_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, pc)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l'); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s (pc)", c); pavone@638: } pavone@638: break; pavone@638: case MODE_ZPC_INDEX_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, zpc, %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s (zpc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: } pavone@638: break; pavone@638: case MODE_ZPC_PREINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_ZPC_POSTINDEX: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd', pavone@638: (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', pavone@638: 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', pavone@638: (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, pavone@638: (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale, pavone@638: decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_ZPC_MEM_INDIRECT: pavone@638: switch (decoded->params.regs.disp_sizes) pavone@638: { pavone@638: case 0x11: pavone@638: //no base displacement or outer displacement pavone@638: ret = sprintf(dst, "%s ([zpc])", c); pavone@638: break; pavone@638: case 0x12: pavone@638: case 0x13: pavone@638: //base displacement only pavone@638: ret = sprintf(dst, "%s ([%d.%c, zpc])", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x21: pavone@638: case 0x31: pavone@638: //outer displacement only pavone@638: ret = sprintf(dst, "%s ([zpc], %d.%c)", c, decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: case 0x22: pavone@638: case 0x23: pavone@638: case 0x32: pavone@638: case 0x33: pavone@638: //both outer and inner displacement pavone@638: ret = sprintf(dst, "%s ([%d.%c, zpc], %d.%c)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp, pavone@638: decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l'); pavone@638: break; pavone@638: } pavone@638: break; pavone@638: case MODE_ZPC_BASE_DISP: pavone@638: if (decoded->params.regs.disp_sizes > 1) pavone@638: { pavone@638: ret = sprintf(dst, "%s (%d.%c, zpc)", c, decoded->params.regs.displacement, pavone@638: decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l'); pavone@638: } else { pavone@638: ret = sprintf(dst, "%s (zpc)", c); pavone@638: } pavone@638: break; pavone@638: #endif pavone@2: default: pavone@636: ret = 0; pavone@0: } pavone@636: #ifdef M68020 pavone@636: if (decoded->addr_mode & M68K_FLAG_BITFIELD) pavone@636: { pavone@636: switch (decoded->bitfield & 0x820) pavone@636: { pavone@636: case 0: pavone@636: return ret + sprintf(dst+ret, " {$%X:%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32); pavone@636: case 0x20: pavone@636: return ret + sprintf(dst+ret, " {$%X:d%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x7); pavone@636: case 0x800: pavone@636: return ret + sprintf(dst+ret, " {d%d:%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32); pavone@636: case 0x820: pavone@636: return ret + sprintf(dst+ret, " {d%d:d%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x7); pavone@636: } pavone@636: } pavone@636: #endif pavone@636: return ret; pavone@0: } pavone@2: pavone@634: int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data) pavone@13: { pavone@13: int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1; pavone@13: char *rtype, *last_rtype; pavone@13: int oplen; pavone@13: if (decoded->addr_mode == MODE_REG) { pavone@13: if (other->addr_mode == MODE_AREG_PREDEC) { pavone@13: bit = 15; pavone@13: dir = -1; pavone@13: } else { pavone@69: dir = 1; pavone@69: bit = 0; pavone@13: } pavone@68: if (need_comma) { pavone@68: strcat(dst, ", "); pavone@68: oplen = 2; pavone@68: } else { pavone@68: strcat(dst, " "); pavone@68: oplen = 1; pavone@68: } pavone@68: for (reg=0; bit < 16 && bit > -1; bit += dir, reg++) { pavone@15: if (decoded->params.immed & (1 << bit)) { pavone@13: if (reg > 7) { pavone@13: rtype = "a"; pavone@13: regnum = reg - 8; pavone@13: } else { pavone@13: rtype = "d"; pavone@13: regnum = reg; pavone@13: } pavone@13: if (last >= 0 && last == regnum - 1 && lastreg == reg - 1) { pavone@13: last = regnum; pavone@13: lastreg = reg; pavone@13: } else if(last >= 0) { pavone@13: if (first != last) { pavone@13: oplen += sprintf(dst + oplen, "-%s%d/%s%d",last_rtype, last, rtype, regnum); pavone@13: } else { pavone@13: oplen += sprintf(dst + oplen, "/%s%d", rtype, regnum); pavone@13: } pavone@13: first = last = regnum; pavone@13: last_rtype = rtype; pavone@13: lastreg = reg; pavone@13: } else { pavone@13: oplen += sprintf(dst + oplen, "%s%d", rtype, regnum); pavone@13: first = last = regnum; pavone@13: last_rtype = rtype; pavone@13: lastreg = reg; pavone@13: } pavone@13: } pavone@13: } pavone@13: if (last >= 0 && last != first) { pavone@13: oplen += sprintf(dst + oplen, "-%s%d", last_rtype, last); pavone@13: } pavone@13: return oplen; pavone@13: } else { pavone@634: return m68k_disasm_op(decoded, dst, need_comma, labels, address, label_fun, data); pavone@13: } pavone@13: } pavone@13: pavone@634: int m68k_default_label_fun(char * dst, uint32_t address, void * data) pavone@634: { pavone@634: return sprintf(dst, "ADR_%X", address); pavone@634: } pavone@634: pavone@634: int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels, format_label_fun label_fun, void * data) pavone@2: { pavone@2: int ret,op1len; pavone@2: uint8_t size; pavone@13: char * special_op = "CCR"; pavone@13: switch (decoded->op) pavone@13: { pavone@13: case M68K_BCC: pavone@13: case M68K_DBCC: pavone@13: case M68K_SCC: pavone@2: ret = strlen(mnemonics[decoded->op]) - 2; pavone@2: memcpy(dst, mnemonics[decoded->op], ret); pavone@2: dst[ret] = 0; pavone@50: strcpy(dst+ret, cond_mnem[decoded->extra.cond]); pavone@2: ret = strlen(dst); pavone@50: if (decoded->op != M68K_SCC) { pavone@134: if (labels) { pavone@134: if (decoded->op == M68K_DBCC) { pavone@634: ret += sprintf(dst+ret, " d%d, ", decoded->dst.params.regs.pri); pavone@634: ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data); pavone@134: } else { pavone@634: dst[ret++] = ' '; pavone@634: ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data); pavone@134: } pavone@54: } else { pavone@134: if (decoded->op == M68K_DBCC) { pavone@134: ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); pavone@134: } else { pavone@134: ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); pavone@134: } pavone@54: } pavone@50: return ret; pavone@50: } pavone@13: break; pavone@13: case M68K_BSR: pavone@134: if (labels) { pavone@634: ret = sprintf(dst, "bsr%s ", decoded->variant == VAR_BYTE ? ".s" : ""); pavone@634: ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data); pavone@134: } else { pavone@134: ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed); pavone@134: } pavone@50: return ret; pavone@13: case M68K_MOVE_FROM_SR: pavone@13: ret = sprintf(dst, "%s", mnemonics[decoded->op]); pavone@13: ret += sprintf(dst + ret, " SR"); pavone@634: ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1, labels, decoded->address, label_fun, data); pavone@13: return ret; pavone@13: case M68K_ANDI_SR: pavone@13: case M68K_EORI_SR: pavone@13: case M68K_MOVE_SR: pavone@13: case M68K_ORI_SR: pavone@13: special_op = "SR"; pavone@13: case M68K_ANDI_CCR: pavone@13: case M68K_EORI_CCR: pavone@13: case M68K_MOVE_CCR: pavone@13: case M68K_ORI_CCR: pavone@13: ret = sprintf(dst, "%s", mnemonics[decoded->op]); pavone@634: ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@13: ret += sprintf(dst + ret, ", %s", special_op); pavone@13: return ret; pavone@50: case M68K_MOVE_USP: pavone@50: ret = sprintf(dst, "%s", mnemonics[decoded->op]); pavone@50: if (decoded->src.addr_mode != MODE_UNUSED) { pavone@634: ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@50: ret += sprintf(dst + ret, ", USP"); pavone@50: } else { pavone@50: ret += sprintf(dst + ret, "USP, "); pavone@634: ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@50: } pavone@50: return ret; pavone@630: case M68K_INVALID: pavone@630: ret = sprintf(dst, "dc.w $%X", decoded->src.params.immed); pavone@630: return ret; pavone@630: #ifdef M68010 pavone@630: case M68K_MOVEC: pavone@630: ret = sprintf(dst, "%s ", mnemonics[decoded->op]); pavone@630: if (decoded->src.addr_mode == MODE_UNUSED) { pavone@630: ret += sprintf(dst + ret, "%s, ", cr_mnem[decoded->src.params.immed]); pavone@634: ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@630: } else { pavone@634: ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@630: ret += sprintf(dst + ret, ", %s", cr_mnem[decoded->dst.params.immed]); pavone@630: } pavone@630: return ret; pavone@630: #endif pavone@13: default: pavone@2: size = decoded->extra.size; pavone@518: ret = sprintf(dst, "%s%s%s", pavone@518: mnemonics[decoded->op], pavone@518: decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""), pavone@13: size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : ""))); pavone@2: } pavone@13: if (decoded->op == M68K_MOVEM) { pavone@634: op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@13: ret += op1len; pavone@634: ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len, labels, decoded->address, label_fun, data); pavone@13: } else { pavone@634: op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data); pavone@13: ret += op1len; pavone@634: ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len, labels, decoded->address, label_fun, data); pavone@13: } pavone@2: return ret; pavone@2: } pavone@2: pavone@134: int m68k_disasm(m68kinst * decoded, char * dst) pavone@134: { pavone@634: return m68k_disasm_ex(decoded, dst, 0, NULL, NULL); pavone@134: } pavone@134: pavone@634: int m68k_disasm_labels(m68kinst * decoded, char * dst, format_label_fun label_fun, void * data) pavone@134: { pavone@634: if (!label_fun) pavone@634: { pavone@634: label_fun = m68k_default_label_fun; pavone@634: } pavone@634: return m68k_disasm_ex(decoded, dst, 1, label_fun, data); pavone@134: }