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 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;

40
dis.c
View File

@ -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;

24
dis.h
View File

@ -19,6 +19,7 @@
#ifndef DIS_H_
#include <stdint.h>
#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 */

View File

@ -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 <opcode>\n"
" byte|word\n"
" byte|word|aword\n"
" jump|single|double|noarg\n"
" src <value>\n"
" dst <value>\n"