dis: decode extended double-operand instructions.

This commit is contained in:
Daniel Beer 2010-08-10 13:27:35 +12:00
parent 8846186979
commit 5994804181
3 changed files with 90 additions and 25 deletions

View File

@ -136,6 +136,8 @@ static int dis_format(stab_t stab, char *buf, int max_len,
suffix = ".B";
else if (insn->dsize == MSP430_DSIZE_AWORD)
suffix = ".A";
else if (insn->dsize == MSP430_DSIZE_UNKNOWN)
suffix = ".?";
len = snprintf(buf + total, max_len - total,
"\x1b[36m%s%s\x1b[0m", opname, suffix);

90
dis.c
View File

@ -26,6 +26,7 @@
#include "util.h"
#define ALL_ONES 0xfffff
#define EXTENSION_BIT 0x20000
/**********************************************************************/
/* Disassembler
@ -402,43 +403,72 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
struct msp430_instruction *insn)
{
uint16_t op;
uint16_t ex_word = 0;
int ret;
address_t ds_mask = ALL_ONES;
memset(insn, 0, sizeof(*insn));
insn->offset = offset;
/* Perform decoding */
if (len < 2)
return -1;
insn->offset = offset;
op = (code[1] << 8) | code[0];
if ((op & 0xf000) == 0x1000)
insn->itype = MSP430_ITYPE_SINGLE;
else if ((op & 0xff00) >= 0x2000 &&
(op & 0xff00) < 0x4000)
insn->itype = MSP430_ITYPE_JUMP;
else if ((op & 0xf000) >= 0x4000)
insn->itype = MSP430_ITYPE_DOUBLE;
else
return -1;
if ((op & 0xf800) == 0x1800) {
ex_word = op;
code += 2;
offset += 2;
len -= 2;
switch (insn->itype) {
case MSP430_ITYPE_SINGLE:
ret = decode_single(code, offset, len, insn);
break;
if (len < 2)
return -1;
op = (code[1] << 8) | code[0];
case MSP430_ITYPE_DOUBLE:
ret = decode_double(code, offset, len, insn);
break;
if ((op & 0xff00) >= 0x4000) {
insn->itype = MSP430_ITYPE_DOUBLE;
ret = decode_double(code, offset, len, insn);
insn->op |= EXTENSION_BIT;
} else {
return -1;
}
case MSP430_ITYPE_JUMP:
ret = decode_jump(code, offset, len, insn);
break;
if (insn->dst_mode == MSP430_AMODE_REGISTER &&
(insn->itype == MSP430_ITYPE_SINGLE ||
insn->src_mode == MSP430_AMODE_REGISTER)) {
insn->zero_carry = (ex_word >> 8) & 1;
insn->rep_register = (ex_word >> 7) & 1;
insn->rep_index = ex_word & 0xf;
} else {
insn->dst_addr |= (ex_word & 0xf) << 16;
insn->src_addr |= ((ex_word >> 6) & 0xf) << 16;
}
default: break;
if (ex_word & 0x40) {
if (insn->dsize == MSP430_DSIZE_BYTE)
insn->dsize = MSP430_DSIZE_AWORD;
else
insn->dsize = MSP430_DSIZE_UNKNOWN;
}
} else {
if ((op & 0xf000) == 0x1000) {
insn->itype = MSP430_ITYPE_SINGLE;
ret = decode_single(code, offset, len, insn);
} else if ((op & 0xff00) >= 0x2000 &&
(op & 0xff00) < 0x4000) {
insn->itype = MSP430_ITYPE_JUMP;
ret = decode_jump(code, offset, len, insn);
} else if ((op & 0xf000) >= 0x4000) {
insn->itype = MSP430_ITYPE_DOUBLE;
ret = decode_double(code, offset, len, insn);
} else {
return -1;
}
}
/* Interpret "emulated" instructions, constant generation, and
* trim data sizes.
*/
find_cgens(insn);
find_emulated_ops(insn);
@ -517,7 +547,21 @@ static const struct {
{MSP430_OP_SETC, "SETC"},
{MSP430_OP_SETN, "SETN"},
{MSP430_OP_SETZ, "SETZ"},
{MSP430_OP_TST, "TST"}
{MSP430_OP_TST, "TST"},
/* MSP430X double operand */
{MSP430_OP_MOVX, "MOVX"},
{MSP430_OP_ADDX, "ADDX"},
{MSP430_OP_ADDCX, "ADDCX"},
{MSP430_OP_SUBCX, "SUBCX"},
{MSP430_OP_SUBX, "SUBX"},
{MSP430_OP_CMPX, "CMPX"},
{MSP430_OP_DADDX, "DADDX"},
{MSP430_OP_BITX, "BITX"},
{MSP430_OP_BICX, "BICX"},
{MSP430_OP_BISX, "BISX"},
{MSP430_OP_XORX, "XORX"},
{MSP430_OP_ANDX, "ANDX"}
};
/* Return the mnemonic for an operation, if possible. */

23
dis.h
View File

@ -109,7 +109,8 @@ typedef enum {
typedef enum {
MSP430_DSIZE_BYTE,
MSP430_DSIZE_WORD,
MSP430_DSIZE_AWORD
MSP430_DSIZE_AWORD,
MSP430_DSIZE_UNKNOWN
} msp430_dsize_t;
/* MSP430 operations.
@ -182,7 +183,21 @@ typedef enum {
MSP430_OP_SETC = 0x10014,
MSP430_OP_SETN = 0x10015,
MSP430_OP_SETZ = 0x10016,
MSP430_OP_TST = 0x10017
MSP430_OP_TST = 0x10017,
/* MSP430X double operand */
MSP430_OP_MOVX = 0x24000,
MSP430_OP_ADDX = 0x25000,
MSP430_OP_ADDCX = 0x26000,
MSP430_OP_SUBCX = 0x27000,
MSP430_OP_SUBX = 0x28000,
MSP430_OP_CMPX = 0x29000,
MSP430_OP_DADDX = 0x2A000,
MSP430_OP_BITX = 0x2B000,
MSP430_OP_BICX = 0x2C000,
MSP430_OP_BISX = 0x2D000,
MSP430_OP_XORX = 0x2E000,
MSP430_OP_ANDX = 0x2F000
} msp430_op_t;
/* This represents a decoded instruction. All decoded addresses are
@ -205,6 +220,10 @@ struct msp430_instruction {
msp430_amode_t dst_mode;
address_t dst_addr;
msp430_reg_t dst_reg;
int rep_index;
int rep_register;
int zero_carry;
};
/* Decode a single instruction.