dis: decode address instructions.

This commit is contained in:
Daniel Beer 2010-08-10 15:47:36 +12:00
parent 3bec9b02cf
commit 5fe3be27d2
3 changed files with 142 additions and 9 deletions

View File

@ -139,6 +139,11 @@ static int dis_format(stab_t stab, char *buf, int max_len,
else if (insn->dsize == MSP430_DSIZE_UNKNOWN)
suffix = ".?";
/* 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)
suffix = "";
len = snprintf(buf + total, max_len - total,
"\x1b[36m%s%s\x1b[0m", opname, suffix);
tlen = textlen(buf + total);

140
dis.c
View File

@ -32,6 +32,128 @@
/* Disassembler
*/
static int decode_00xx(const uint8_t *code, address_t offset,
address_t len, struct msp430_instruction *insn)
{
uint16_t op = code[0] | (code[1] << 8);
int subtype = (op >> 4) & 0xf;
int have_arg = 0;
address_t arg;
/* Parameters common to most cases */
insn->op = MSP430_OP_MOVA;
insn->itype = MSP430_ITYPE_DOUBLE;
insn->dsize = MSP430_DSIZE_AWORD;
insn->dst_mode = MSP430_AMODE_REGISTER;
insn->dst_reg = op & 0xf;
insn->src_mode = MSP430_AMODE_REGISTER;
insn->src_reg = (op >> 8) & 0xf;
if (len >= 4) {
have_arg = 1;
arg = code[2] | (code[3] << 8);
}
switch (subtype) {
case 0:
insn->src_mode = MSP430_AMODE_INDIRECT;
return 2;
case 1:
insn->src_mode = MSP430_AMODE_INDIRECT_INC;
return 2;
case 2:
if (!have_arg)
return -1;
insn->src_mode = MSP430_AMODE_ABSOLUTE;
insn->src_addr = ((op & 0xf00) << 8) | arg;
return 4;
case 3:
if (!have_arg)
return -1;
insn->src_mode = MSP430_AMODE_INDEXED;
insn->src_addr = arg;
return 4;
case 4:
case 5:
/* RxxM */
insn->itype = MSP430_ITYPE_SINGLE;
insn->op = op & 0xf3e0;
insn->dst_mode = MSP430_AMODE_REGISTER;
insn->dst_reg = op & 0xf;
insn->rep_index = (op >> 10) & 3;
insn->dsize = (op & 0x0010) ?
MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD;
return 2;
case 6:
if (!have_arg)
return -1;
insn->dst_mode = MSP430_AMODE_ABSOLUTE;
insn->dst_addr = ((op & 0xf) << 16) | arg;
return 4;
case 7:
if (!have_arg)
return -1;
insn->dst_mode = MSP430_AMODE_INDEXED;
insn->dst_addr = arg;
return 4;
case 8:
if (!have_arg)
return -1;
insn->src_mode = MSP430_AMODE_IMMEDIATE;
insn->src_addr = ((op & 0xf00) << 8) | arg;
return 4;
case 9:
if (!have_arg)
return -1;
insn->op = MSP430_OP_CMPA;
insn->src_mode = MSP430_AMODE_IMMEDIATE;
insn->src_addr = ((op & 0xf00) << 8) | arg;
return 4;
case 10:
if (!have_arg)
return -1;
insn->op = MSP430_OP_ADDA;
insn->src_mode = MSP430_AMODE_IMMEDIATE;
insn->src_addr = ((op & 0xf00) << 8) | arg;
return 4;
case 11:
if (!have_arg)
return -1;
insn->op = MSP430_OP_SUBA;
insn->src_mode = MSP430_AMODE_IMMEDIATE;
insn->src_addr = ((op & 0xf00) << 8) | arg;
return 4;
case 12:
return 2;
case 13:
insn->op = MSP430_OP_CMPA;
return 2;
case 14:
insn->op = MSP430_OP_ADDA;
return 2;
case 15:
insn->op = MSP430_OP_SUBA;
return 2;
}
return -1;
}
static int decode_13xx(const uint8_t *code, address_t offset,
address_t len, struct msp430_instruction *insn)
{
@ -522,16 +644,10 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
insn->dsize = MSP430_DSIZE_UNKNOWN;
}
} else {
if ((op & 0xf0e0) == 0x0040) {
insn->itype = MSP430_ITYPE_SINGLE;
insn->op = op & 0xf3e0;
insn->dst_mode = MSP430_AMODE_REGISTER;
insn->dst_reg = op & 0xf;
insn->rep_index = (op >> 10) & 3;
insn->dsize = (op & 0x0010) ?
MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD;
ret = 2;
if ((op & 0xf000) == 0x0000) {
ret = decode_00xx(code, offset, len, insn);
} else if ((op & 0xfc00) == 0x1400) {
/* PUSHM/POPM */
insn->itype = MSP430_ITYPE_SINGLE;
insn->op = op & 0xfe00;
insn->dst_mode = MSP430_AMODE_REGISTER;
@ -669,6 +785,12 @@ static const struct {
{MSP430_OP_PUSHM, "PUSHM"},
{MSP430_OP_POPM, "POPM"},
/* MSP430X address instructions */
{MSP430_OP_MOVA, "MOVA"},
{MSP430_OP_CMPA, "CMPA"},
{MSP430_OP_SUBA, "SUBA"},
{MSP430_OP_ADDA, "ADDA"},
/* MSP430X group 00xx, non-address */
{MSP430_OP_RRCM, "RRCM"},
{MSP430_OP_RRAM, "RRAM"},

6
dis.h
View File

@ -214,6 +214,12 @@ typedef enum {
MSP430_OP_PUSHM = 0x1400,
MSP430_OP_POPM = 0x1600,
/* MSP430X address instructions */
MSP430_OP_MOVA = 0x0000,
MSP430_OP_CMPA = 0x0090,
MSP430_OP_ADDA = 0x00A0,
MSP430_OP_SUBA = 0x00B0,
/* MSP430X group 00xx, non-address */
MSP430_OP_RRCM = 0x0040,
MSP430_OP_RRAM = 0x0140,