From ccc5854854e19e8cbe744b76769db48f2b36fc2c Mon Sep 17 00:00:00 2001 From: Daniel Beer Date: Tue, 10 Aug 2010 16:26:45 +1200 Subject: [PATCH] dis: decode MSP430X emulated instructions. --- cproc_util.c | 3 +- dis.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++- dis.h | 22 +++++++- 3 files changed, 173 insertions(+), 3 deletions(-) diff --git a/cproc_util.c b/cproc_util.c index e99de4c..c811788 100644 --- a/cproc_util.c +++ b/cproc_util.c @@ -141,7 +141,8 @@ static int dis_format(stab_t stab, char *buf, int max_len, /* Don't show the .A suffix for these instructions */ if (insn->op == MSP430_OP_MOVA || insn->op == MSP430_OP_CMPA || - insn->op == MSP430_OP_SUBA || insn->op == MSP430_OP_ADDA) + insn->op == MSP430_OP_SUBA || insn->op == MSP430_OP_ADDA || + insn->op == MSP430_OP_BRA || insn->op == MSP430_OP_RETA) suffix = ""; len = snprintf(buf + total, max_len - total, diff --git a/dis.c b/dis.c index 366b05a..dc9840f 100644 --- a/dis.c +++ b/dis.c @@ -465,6 +465,31 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_ADDA: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + insn->src_addr == 2) { + insn->op = MSP430_OP_INCDA; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + + case MSP430_OP_ADDX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE) { + if (insn->src_addr == 1) { + insn->op = MSP430_OP_INCX; + insn->itype = MSP430_ITYPE_SINGLE; + } else if (insn->src_addr == 2) { + insn->op = MSP430_OP_INCDX; + insn->itype = MSP430_ITYPE_SINGLE; + } + } else if (insn->dst_mode == insn->src_mode && + insn->dst_reg == insn->src_reg && + insn->dst_addr == insn->src_addr) { + insn->op = MSP430_OP_RLAX; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + case MSP430_OP_ADDC: if (insn->src_mode == MSP430_AMODE_IMMEDIATE && !insn->src_addr) { @@ -478,6 +503,19 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_ADDCX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + !insn->src_addr) { + insn->op = MSP430_OP_ADCX; + insn->itype = MSP430_ITYPE_SINGLE; + } else if (insn->dst_mode == insn->src_mode && + insn->dst_reg == insn->src_reg && + insn->dst_addr == insn->src_addr) { + insn->op = MSP430_OP_RLCX; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + case MSP430_OP_BIC: if (insn->dst_mode == MSP430_AMODE_REGISTER && insn->dst_reg == MSP430_REG_SR && @@ -526,6 +564,22 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_CMPA: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + !insn->src_addr) { + insn->op = MSP430_OP_TSTA; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + + case MSP430_OP_CMPX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + !insn->src_addr) { + insn->op = MSP430_OP_TSTX; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + case MSP430_OP_DADD: if (insn->src_mode == MSP430_AMODE_IMMEDIATE && !insn->src_addr) { @@ -534,6 +588,14 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_DADDX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + !insn->src_addr) { + insn->op = MSP430_OP_DADCX; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + case MSP430_OP_MOV: if (insn->src_mode == MSP430_AMODE_INDIRECT_INC && insn->src_reg == MSP430_REG_SP) { @@ -565,6 +627,37 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_MOVA: + if (insn->src_mode == MSP430_AMODE_INDIRECT_INC && + insn->src_reg == MSP430_REG_SP) { + if (insn->dst_mode == MSP430_AMODE_REGISTER && + insn->dst_reg == MSP430_REG_PC) { + insn->op = MSP430_OP_RETA; + insn->itype = MSP430_ITYPE_NOARG; + } else { + insn->op = MSP430_OP_POPX; + insn->itype = MSP430_ITYPE_SINGLE; + } + } else if (insn->dst_mode == MSP430_AMODE_REGISTER && + insn->dst_reg == MSP430_REG_PC) { + insn->op = MSP430_OP_BRA; + insn->itype = MSP430_ITYPE_SINGLE; + insn->dst_mode = insn->src_mode; + insn->dst_reg = insn->src_reg; + insn->dst_addr = insn->src_addr; + } else if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + !insn->src_addr) { + if (insn->dst_mode == MSP430_AMODE_REGISTER && + insn->dst_reg == MSP430_REG_R3) { + insn->op = MSP430_OP_NOP; + insn->itype = MSP430_ITYPE_NOARG; + } else { + insn->op = MSP430_OP_CLRX; + insn->itype = MSP430_ITYPE_SINGLE; + } + } + break; + case MSP430_OP_SUB: if (insn->src_mode == MSP430_AMODE_IMMEDIATE) { if (insn->src_addr == 1) { @@ -577,6 +670,26 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_SUBA: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + insn->src_addr == 2) { + insn->op = MSP430_OP_DECDA; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + + case MSP430_OP_SUBX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE) { + if (insn->src_addr == 1) { + insn->op = MSP430_OP_DECX; + insn->itype = MSP430_ITYPE_SINGLE; + } else if (insn->src_addr == 2) { + insn->op = MSP430_OP_DECDX; + insn->itype = MSP430_ITYPE_SINGLE; + } + } + break; + case MSP430_OP_SUBC: if (insn->src_mode == MSP430_AMODE_IMMEDIATE && !insn->src_addr) { @@ -585,6 +698,14 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_SUBCX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + !insn->src_addr) { + insn->op = MSP430_OP_SECX; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + case MSP430_OP_XOR: if (insn->src_mode == MSP430_AMODE_IMMEDIATE && insn->src_addr == ALL_ONES) { @@ -593,6 +714,14 @@ static void find_emulated_ops(struct msp430_instruction *insn) } break; + case MSP430_OP_XORX: + if (insn->src_mode == MSP430_AMODE_IMMEDIATE && + insn->src_addr == ALL_ONES) { + insn->op = MSP430_OP_INVX; + insn->itype = MSP430_ITYPE_SINGLE; + } + break; + default: break; } } @@ -798,7 +927,27 @@ static const struct { {MSP430_OP_RRCM, "RRCM"}, {MSP430_OP_RRAM, "RRAM"}, {MSP430_OP_RLAM, "RLAM"}, - {MSP430_OP_RRUM, "RRUM"} + {MSP430_OP_RRUM, "RRUM"}, + + /* MSP430X emulated instructions */ + {MSP430_OP_ADCX, "ADCX"}, + {MSP430_OP_BRA, "BRA"}, + {MSP430_OP_RETA, "RETA"}, + {MSP430_OP_CLRX, "CLRX"}, + {MSP430_OP_DADCX, "DADCX"}, + {MSP430_OP_DECX, "DECX"}, + {MSP430_OP_DECDA, "DECDA"}, + {MSP430_OP_DECDX, "DECDX"}, + {MSP430_OP_INCX, "INCX"}, + {MSP430_OP_INCDA, "INCDA"}, + {MSP430_OP_INVX, "INVX"}, + {MSP430_OP_RLAX, "RLAX"}, + {MSP430_OP_RLCX, "RLCX"}, + {MSP430_OP_SECX, "SECX"}, + {MSP430_OP_TSTA, "TSTA"}, + {MSP430_OP_TSTX, "TSTX"}, + {MSP430_OP_POPX, "POPX"}, + {MSP430_OP_INCDX, "INCDX"} }; /* Return the mnemonic for an operation, if possible. */ diff --git a/dis.h b/dis.h index e5781cd..174b35a 100644 --- a/dis.h +++ b/dis.h @@ -224,7 +224,27 @@ typedef enum { MSP430_OP_RRCM = 0x0040, MSP430_OP_RRAM = 0x0140, MSP430_OP_RLAM = 0x0240, - MSP430_OP_RRUM = 0x0340 + MSP430_OP_RRUM = 0x0340, + + /* MSP430X emulated instructions */ + MSP430_OP_ADCX = 0x40000, + MSP430_OP_BRA = 0x40001, + MSP430_OP_RETA = 0x40002, + MSP430_OP_CLRX = 0x40003, + MSP430_OP_DADCX = 0x40004, + MSP430_OP_DECX = 0x40005, + MSP430_OP_DECDA = 0x40006, + MSP430_OP_DECDX = 0x40007, + MSP430_OP_INCX = 0x40008, + MSP430_OP_INCDA = 0x40009, + MSP430_OP_INVX = 0x4000A, + MSP430_OP_RLAX = 0x4000B, + MSP430_OP_RLCX = 0x4000C, + MSP430_OP_SECX = 0x4000D, + MSP430_OP_TSTA = 0x4000E, + MSP430_OP_TSTX = 0x4000F, + MSP430_OP_POPX = 0x40010, + MSP430_OP_INCDX = 0x40011, } msp430_op_t; /* This represents a decoded instruction. All decoded addresses are