dis: alter interface to allow for MSP430X instruction set.

This commit is contained in:
Daniel Beer 2010-08-10 12:21:16 +12:00
parent 636e11b626
commit 8846186979
4 changed files with 69 additions and 31 deletions

View File

@ -127,13 +127,18 @@ static int dis_format(stab_t stab, char *buf, int max_len,
int tlen; int tlen;
int total = 0; int total = 0;
const char *opname = dis_opcode_name(insn->op); const char *opname = dis_opcode_name(insn->op);
const char *suffix = "";
if (!opname) if (!opname)
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, len = snprintf(buf + total, max_len - total,
"\x1b[36m%s%s\x1b[0m", opname, "\x1b[36m%s%s\x1b[0m", opname, suffix);
insn->is_byte_op ? ".B" : "");
tlen = textlen(buf + total); tlen = textlen(buf + total);
total += len; total += len;

40
dis.c
View File

@ -25,6 +25,8 @@
#include "dis.h" #include "dis.h"
#include "util.h" #include "util.h"
#define ALL_ONES 0xfffff
/**********************************************************************/ /**********************************************************************/
/* Disassembler /* Disassembler
*/ */
@ -34,14 +36,14 @@
* Returns the number of bytes consumed in decoding, or -1 if the a * Returns the number of bytes consumed in decoding, or -1 if the a
* valid single-operand instruction could not be found. * valid single-operand instruction could not be found.
*/ */
static int decode_single(const uint8_t *code, uint16_t offset, static int decode_single(const uint8_t *code, address_t offset,
uint16_t size, struct msp430_instruction *insn) address_t size, struct msp430_instruction *insn)
{ {
uint16_t op = (code[1] << 8) | code[0]; uint16_t op = (code[1] << 8) | code[0];
int need_arg = 0; int need_arg = 0;
insn->op = op & 0xff80; 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_mode = (op >> 4) & 0x3;
insn->dst_reg = op & 0xf; 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 * Returns the number of bytes consumed or -1 if a valid instruction
* could not be found. * could not be found.
*/ */
static int decode_double(const uint8_t *code, uint16_t offset, static int decode_double(const uint8_t *code, address_t offset,
uint16_t size, struct msp430_instruction *insn) address_t size, struct msp430_instruction *insn)
{ {
uint16_t op = (code[1] << 8) | code[0]; uint16_t op = (code[1] << 8) | code[0];
int need_src = 0; int need_src = 0;
@ -95,7 +97,7 @@ static int decode_double(const uint8_t *code, uint16_t offset,
int ret = 2; int ret = 2;
insn->op = op & 0xf000; 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_mode = (op >> 4) & 0x3;
insn->src_reg = (op >> 8) & 0xf; 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 * All jump instructions are one word in length, so this function
* always returns 2 (to indicate the consumption of 2 bytes). * 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) struct msp430_instruction *insn)
{ {
uint16_t op = (code[1] << 8) | code[0]; 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, static void remap_cgen(msp430_amode_t *mode,
uint16_t *addr, address_t *addr,
msp430_reg_t *reg) msp430_reg_t *reg)
{ {
if (*reg == MSP430_REG_SR) { if (*reg == MSP430_REG_SR) {
@ -212,7 +214,7 @@ static void remap_cgen(msp430_amode_t *mode,
else if (*mode == MSP430_AMODE_INDIRECT) else if (*mode == MSP430_AMODE_INDIRECT)
*addr = 2; *addr = 2;
else if (*mode == MSP430_AMODE_INDIRECT_INC) else if (*mode == MSP430_AMODE_INDIRECT_INC)
*addr = 0xffff; *addr = ALL_ONES;
*mode = MSP430_AMODE_IMMEDIATE; *mode = MSP430_AMODE_IMMEDIATE;
} }
@ -377,7 +379,7 @@ static void find_emulated_ops(struct msp430_instruction *insn)
case MSP430_OP_XOR: case MSP430_OP_XOR:
if (insn->src_mode == MSP430_AMODE_IMMEDIATE && if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
insn->src_addr == 0xffff) { insn->src_addr == ALL_ONES) {
insn->op = MSP430_OP_INV; insn->op = MSP430_OP_INV;
insn->itype = MSP430_ITYPE_SINGLE; 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 * successful, the decoded instruction is written into the structure
* pointed to by insn. * 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) struct msp430_instruction *insn)
{ {
uint16_t op; uint16_t op;
int ret; int ret;
address_t ds_mask = ALL_ONES;
memset(insn, 0, sizeof(*insn)); 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_cgens(insn);
find_emulated_ops(insn); find_emulated_ops(insn);
if (insn->is_byte_op) { if (insn->dsize == MSP430_DSIZE_BYTE)
if (insn->src_mode == MSP430_AMODE_IMMEDIATE) ds_mask = 0xff;
insn->src_addr &= 0xff; else if (insn->dsize == MSP430_DSIZE_WORD)
if (insn->dst_mode == MSP430_AMODE_IMMEDIATE) ds_mask = 0xffff;
insn->dst_addr &= 0xff;
} 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; insn->len = ret;
return ret; return ret;

24
dis.h
View File

@ -19,6 +19,7 @@
#ifndef DIS_H_ #ifndef DIS_H_
#include <stdint.h> #include <stdint.h>
#include "util.h"
/* Addressing modes. /* Addressing modes.
* *
@ -98,6 +99,19 @@ typedef enum {
MSP430_ITYPE_SINGLE MSP430_ITYPE_SINGLE
} msp430_itype_t; } 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. /* MSP430 operations.
* *
* Some of these are emulated instructions. Emulated instructions are * 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. * For jump instructions, the target address is stored in dst_operand.
*/ */
struct msp430_instruction { struct msp430_instruction {
uint16_t offset; address_t offset;
int len; int len;
msp430_op_t op; msp430_op_t op;
msp430_itype_t itype; msp430_itype_t itype;
int is_byte_op; msp430_dsize_t dsize;
msp430_amode_t src_mode; msp430_amode_t src_mode;
uint16_t src_addr; address_t src_addr;
msp430_reg_t src_reg; msp430_reg_t src_reg;
msp430_amode_t dst_mode; msp430_amode_t dst_mode;
uint16_t dst_addr; address_t dst_addr;
msp430_reg_t dst_reg; msp430_reg_t dst_reg;
}; };
@ -203,7 +217,7 @@ struct msp430_instruction {
* pointed to by insn. * pointed to by insn.
*/ */
int dis_decode(const uint8_t *code, int dis_decode(const uint8_t *code,
uint16_t offset, uint16_t len, address_t offset, address_t len,
struct msp430_instruction *insn); struct msp430_instruction *insn);
/* Look up names for registers and opcodes */ /* Look up names for registers and opcodes */

View File

@ -36,7 +36,7 @@
*/ */
#define ISEARCH_OPCODE 0x0001 #define ISEARCH_OPCODE 0x0001
#define ISEARCH_BW 0x0002 #define ISEARCH_DSIZE 0x0002
#define ISEARCH_SRC_ADDR 0x0004 #define ISEARCH_SRC_ADDR 0x0004
#define ISEARCH_DST_ADDR 0x0008 #define ISEARCH_DST_ADDR 0x0008
#define ISEARCH_SRC_MODE 0x0010 #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, static int isearch_bw(cproc_t cp, const char *term, char **arg,
struct isearch_query *q) struct isearch_query *q)
{ {
if (q->flags & ISEARCH_BW) { if (q->flags & ISEARCH_DSIZE) {
fprintf(stderr, "isearch: operand size already specified\n"); fprintf(stderr, "isearch: operand size already specified\n");
return -1; return -1;
} }
q->flags |= ISEARCH_BW; q->flags |= ISEARCH_DSIZE;
q->insn.is_byte_op = (toupper(*term) == 'B'); 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; return 0;
} }
@ -268,8 +281,8 @@ static int isearch_match(const struct msp430_instruction *insn,
insn->op != q->insn.op) insn->op != q->insn.op)
return 0; return 0;
if ((q->flags & ISEARCH_BW) && if ((q->flags & ISEARCH_DSIZE) &&
(q->insn.is_byte_op ? 1 : 0) != (insn->is_byte_op ? 1 : 0)) q->insn.dsize != insn->dsize)
return 0; return 0;
if (q->flags & ISEARCH_SRC_ADDR) { 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" " Search for an instruction matching certain search terms. These\n"
" terms may be any of the following:\n" " terms may be any of the following:\n"
" opcode <opcode>\n" " opcode <opcode>\n"
" byte|word\n" " byte|word|aword\n"
" jump|single|double|noarg\n" " jump|single|double|noarg\n"
" src <value>\n" " src <value>\n"
" dst <value>\n" " dst <value>\n"