From 88461869792212ea9367be27f4bda571d991cffc Mon Sep 17 00:00:00 2001 From: Daniel Beer Date: Tue, 10 Aug 2010 12:21:16 +1200 Subject: [PATCH] dis: alter interface to allow for MSP430X instruction set. --- cproc_util.c | 9 +++++++-- dis.c | 40 +++++++++++++++++++++++----------------- dis.h | 24 +++++++++++++++++++----- rtools.c | 27 ++++++++++++++++++++------- 4 files changed, 69 insertions(+), 31 deletions(-) diff --git a/cproc_util.c b/cproc_util.c index ca7c8f2..4a4432a 100644 --- a/cproc_util.c +++ b/cproc_util.c @@ -127,13 +127,18 @@ static int dis_format(stab_t stab, char *buf, int max_len, int tlen; int total = 0; const char *opname = dis_opcode_name(insn->op); + const char *suffix = ""; if (!opname) opname = "???"; + if (insn->dsize == MSP430_DSIZE_BYTE) + suffix = ".B"; + else if (insn->dsize == MSP430_DSIZE_AWORD) + suffix = ".A"; + len = snprintf(buf + total, max_len - total, - "\x1b[36m%s%s\x1b[0m", opname, - insn->is_byte_op ? ".B" : ""); + "\x1b[36m%s%s\x1b[0m", opname, suffix); tlen = textlen(buf + total); total += len; diff --git a/dis.c b/dis.c index 3814ead..607ef84 100644 --- a/dis.c +++ b/dis.c @@ -25,6 +25,8 @@ #include "dis.h" #include "util.h" +#define ALL_ONES 0xfffff + /**********************************************************************/ /* Disassembler */ @@ -34,14 +36,14 @@ * Returns the number of bytes consumed in decoding, or -1 if the a * valid single-operand instruction could not be found. */ -static int decode_single(const uint8_t *code, uint16_t offset, - uint16_t size, struct msp430_instruction *insn) +static int decode_single(const uint8_t *code, address_t offset, + address_t size, struct msp430_instruction *insn) { uint16_t op = (code[1] << 8) | code[0]; int need_arg = 0; insn->op = op & 0xff80; - insn->is_byte_op = op & 0x0400; + insn->dsize = (op & 0x0400) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD; insn->dst_mode = (op >> 4) & 0x3; insn->dst_reg = op & 0xf; @@ -86,8 +88,8 @@ static int decode_single(const uint8_t *code, uint16_t offset, * Returns the number of bytes consumed or -1 if a valid instruction * could not be found. */ -static int decode_double(const uint8_t *code, uint16_t offset, - uint16_t size, struct msp430_instruction *insn) +static int decode_double(const uint8_t *code, address_t offset, + address_t size, struct msp430_instruction *insn) { uint16_t op = (code[1] << 8) | code[0]; int need_src = 0; @@ -95,7 +97,7 @@ static int decode_double(const uint8_t *code, uint16_t offset, int ret = 2; insn->op = op & 0xf000; - insn->is_byte_op = op & 0x0040; + insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD; insn->src_mode = (op >> 4) & 0x3; insn->src_reg = (op >> 8) & 0xf; @@ -175,7 +177,7 @@ static int decode_double(const uint8_t *code, uint16_t offset, * All jump instructions are one word in length, so this function * always returns 2 (to indicate the consumption of 2 bytes). */ -static int decode_jump(const uint8_t *code, uint16_t offset, uint16_t len, +static int decode_jump(const uint8_t *code, address_t offset, address_t len, struct msp430_instruction *insn) { uint16_t op = (code[1] << 8) | code[0]; @@ -193,7 +195,7 @@ static int decode_jump(const uint8_t *code, uint16_t offset, uint16_t len, } static void remap_cgen(msp430_amode_t *mode, - uint16_t *addr, + address_t *addr, msp430_reg_t *reg) { if (*reg == MSP430_REG_SR) { @@ -212,7 +214,7 @@ static void remap_cgen(msp430_amode_t *mode, else if (*mode == MSP430_AMODE_INDIRECT) *addr = 2; else if (*mode == MSP430_AMODE_INDIRECT_INC) - *addr = 0xffff; + *addr = ALL_ONES; *mode = MSP430_AMODE_IMMEDIATE; } @@ -377,7 +379,7 @@ static void find_emulated_ops(struct msp430_instruction *insn) case MSP430_OP_XOR: if (insn->src_mode == MSP430_AMODE_IMMEDIATE && - insn->src_addr == 0xffff) { + insn->src_addr == ALL_ONES) { insn->op = MSP430_OP_INV; insn->itype = MSP430_ITYPE_SINGLE; } @@ -396,11 +398,12 @@ static void find_emulated_ops(struct msp430_instruction *insn) * successful, the decoded instruction is written into the structure * pointed to by insn. */ -int dis_decode(const uint8_t *code, uint16_t offset, uint16_t len, +int dis_decode(const uint8_t *code, address_t offset, address_t len, struct msp430_instruction *insn) { uint16_t op; int ret; + address_t ds_mask = ALL_ONES; memset(insn, 0, sizeof(*insn)); @@ -439,12 +442,15 @@ int dis_decode(const uint8_t *code, uint16_t offset, uint16_t len, find_cgens(insn); find_emulated_ops(insn); - if (insn->is_byte_op) { - if (insn->src_mode == MSP430_AMODE_IMMEDIATE) - insn->src_addr &= 0xff; - if (insn->dst_mode == MSP430_AMODE_IMMEDIATE) - insn->dst_addr &= 0xff; - } + if (insn->dsize == MSP430_DSIZE_BYTE) + ds_mask = 0xff; + else if (insn->dsize == MSP430_DSIZE_WORD) + ds_mask = 0xffff; + + if (insn->src_mode == MSP430_AMODE_IMMEDIATE) + insn->src_addr &= ds_mask; + if (insn->dst_mode == MSP430_AMODE_IMMEDIATE) + insn->dst_addr &= ds_mask; insn->len = ret; return ret; diff --git a/dis.h b/dis.h index 3575600..f8aa4f3 100644 --- a/dis.h +++ b/dis.h @@ -19,6 +19,7 @@ #ifndef DIS_H_ #include +#include "util.h" /* Addressing modes. * @@ -98,6 +99,19 @@ typedef enum { MSP430_ITYPE_SINGLE } msp430_itype_t; +/* MSP430(X) data sizes. + * + * An address-word is a 20-bit value. When stored in memory, they are + * stored as two 16-bit words in the following order: + * + * data[15:0], {12'b0, data[19:16]} + */ +typedef enum { + MSP430_DSIZE_BYTE, + MSP430_DSIZE_WORD, + MSP430_DSIZE_AWORD +} msp430_dsize_t; + /* MSP430 operations. * * Some of these are emulated instructions. Emulated instructions are @@ -177,19 +191,19 @@ typedef enum { * For jump instructions, the target address is stored in dst_operand. */ struct msp430_instruction { - uint16_t offset; + address_t offset; int len; msp430_op_t op; msp430_itype_t itype; - int is_byte_op; + msp430_dsize_t dsize; msp430_amode_t src_mode; - uint16_t src_addr; + address_t src_addr; msp430_reg_t src_reg; msp430_amode_t dst_mode; - uint16_t dst_addr; + address_t dst_addr; msp430_reg_t dst_reg; }; @@ -203,7 +217,7 @@ struct msp430_instruction { * pointed to by insn. */ int dis_decode(const uint8_t *code, - uint16_t offset, uint16_t len, + address_t offset, address_t len, struct msp430_instruction *insn); /* Look up names for registers and opcodes */ diff --git a/rtools.c b/rtools.c index 7dea62c..e91712b 100644 --- a/rtools.c +++ b/rtools.c @@ -36,7 +36,7 @@ */ #define ISEARCH_OPCODE 0x0001 -#define ISEARCH_BW 0x0002 +#define ISEARCH_DSIZE 0x0002 #define ISEARCH_SRC_ADDR 0x0004 #define ISEARCH_DST_ADDR 0x0008 #define ISEARCH_SRC_MODE 0x0010 @@ -80,13 +80,26 @@ static int isearch_opcode(cproc_t cp, const char *term, char **arg, static int isearch_bw(cproc_t cp, const char *term, char **arg, struct isearch_query *q) { - if (q->flags & ISEARCH_BW) { + if (q->flags & ISEARCH_DSIZE) { fprintf(stderr, "isearch: operand size already specified\n"); return -1; } - q->flags |= ISEARCH_BW; - q->insn.is_byte_op = (toupper(*term) == 'B'); + q->flags |= ISEARCH_DSIZE; + switch (toupper(*term)) { + case 'B': + q->insn.dsize = MSP430_DSIZE_BYTE; + break; + + case 'W': + q->insn.dsize = MSP430_DSIZE_WORD; + break; + + case 'A': + q->insn.dsize = MSP430_DSIZE_AWORD; + break; + } + return 0; } @@ -268,8 +281,8 @@ static int isearch_match(const struct msp430_instruction *insn, insn->op != q->insn.op) return 0; - if ((q->flags & ISEARCH_BW) && - (q->insn.is_byte_op ? 1 : 0) != (insn->is_byte_op ? 1 : 0)) + if ((q->flags & ISEARCH_DSIZE) && + q->insn.dsize != insn->dsize) return 0; if (q->flags & ISEARCH_SRC_ADDR) { @@ -967,7 +980,7 @@ static const struct cproc_command rtools_commands[] = { " Search for an instruction matching certain search terms. These\n" " terms may be any of the following:\n" " opcode \n" -" byte|word\n" +" byte|word|aword\n" " jump|single|double|noarg\n" " src \n" " dst \n"