dis: decode extended double-operand instructions.
This commit is contained in:
parent
8846186979
commit
5994804181
|
@ -136,6 +136,8 @@ static int dis_format(stab_t stab, char *buf, int max_len,
|
||||||
suffix = ".B";
|
suffix = ".B";
|
||||||
else if (insn->dsize == MSP430_DSIZE_AWORD)
|
else if (insn->dsize == MSP430_DSIZE_AWORD)
|
||||||
suffix = ".A";
|
suffix = ".A";
|
||||||
|
else if (insn->dsize == MSP430_DSIZE_UNKNOWN)
|
||||||
|
suffix = ".?";
|
||||||
|
|
||||||
len = snprintf(buf + total, max_len - total,
|
len = snprintf(buf + total, max_len - total,
|
||||||
"\x1b[36m%s%s\x1b[0m", opname, suffix);
|
"\x1b[36m%s%s\x1b[0m", opname, suffix);
|
||||||
|
|
90
dis.c
90
dis.c
|
@ -26,6 +26,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define ALL_ONES 0xfffff
|
#define ALL_ONES 0xfffff
|
||||||
|
#define EXTENSION_BIT 0x20000
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* Disassembler
|
/* Disassembler
|
||||||
|
@ -402,43 +403,72 @@ 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;
|
||||||
|
uint16_t ex_word = 0;
|
||||||
int ret;
|
int ret;
|
||||||
address_t ds_mask = ALL_ONES;
|
address_t ds_mask = ALL_ONES;
|
||||||
|
|
||||||
memset(insn, 0, sizeof(*insn));
|
memset(insn, 0, sizeof(*insn));
|
||||||
|
insn->offset = offset;
|
||||||
|
|
||||||
|
/* Perform decoding */
|
||||||
if (len < 2)
|
if (len < 2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
insn->offset = offset;
|
|
||||||
op = (code[1] << 8) | code[0];
|
op = (code[1] << 8) | code[0];
|
||||||
|
|
||||||
if ((op & 0xf000) == 0x1000)
|
if ((op & 0xf800) == 0x1800) {
|
||||||
insn->itype = MSP430_ITYPE_SINGLE;
|
ex_word = op;
|
||||||
else if ((op & 0xff00) >= 0x2000 &&
|
code += 2;
|
||||||
(op & 0xff00) < 0x4000)
|
offset += 2;
|
||||||
insn->itype = MSP430_ITYPE_JUMP;
|
len -= 2;
|
||||||
else if ((op & 0xf000) >= 0x4000)
|
|
||||||
insn->itype = MSP430_ITYPE_DOUBLE;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
switch (insn->itype) {
|
if (len < 2)
|
||||||
case MSP430_ITYPE_SINGLE:
|
return -1;
|
||||||
ret = decode_single(code, offset, len, insn);
|
op = (code[1] << 8) | code[0];
|
||||||
break;
|
|
||||||
|
|
||||||
case MSP430_ITYPE_DOUBLE:
|
if ((op & 0xff00) >= 0x4000) {
|
||||||
ret = decode_double(code, offset, len, insn);
|
insn->itype = MSP430_ITYPE_DOUBLE;
|
||||||
break;
|
ret = decode_double(code, offset, len, insn);
|
||||||
|
insn->op |= EXTENSION_BIT;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
case MSP430_ITYPE_JUMP:
|
if (insn->dst_mode == MSP430_AMODE_REGISTER &&
|
||||||
ret = decode_jump(code, offset, len, insn);
|
(insn->itype == MSP430_ITYPE_SINGLE ||
|
||||||
break;
|
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_cgens(insn);
|
||||||
find_emulated_ops(insn);
|
find_emulated_ops(insn);
|
||||||
|
|
||||||
|
@ -517,7 +547,21 @@ static const struct {
|
||||||
{MSP430_OP_SETC, "SETC"},
|
{MSP430_OP_SETC, "SETC"},
|
||||||
{MSP430_OP_SETN, "SETN"},
|
{MSP430_OP_SETN, "SETN"},
|
||||||
{MSP430_OP_SETZ, "SETZ"},
|
{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. */
|
/* Return the mnemonic for an operation, if possible. */
|
||||||
|
|
23
dis.h
23
dis.h
|
@ -109,7 +109,8 @@ typedef enum {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MSP430_DSIZE_BYTE,
|
MSP430_DSIZE_BYTE,
|
||||||
MSP430_DSIZE_WORD,
|
MSP430_DSIZE_WORD,
|
||||||
MSP430_DSIZE_AWORD
|
MSP430_DSIZE_AWORD,
|
||||||
|
MSP430_DSIZE_UNKNOWN
|
||||||
} msp430_dsize_t;
|
} msp430_dsize_t;
|
||||||
|
|
||||||
/* MSP430 operations.
|
/* MSP430 operations.
|
||||||
|
@ -182,7 +183,21 @@ typedef enum {
|
||||||
MSP430_OP_SETC = 0x10014,
|
MSP430_OP_SETC = 0x10014,
|
||||||
MSP430_OP_SETN = 0x10015,
|
MSP430_OP_SETN = 0x10015,
|
||||||
MSP430_OP_SETZ = 0x10016,
|
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;
|
} msp430_op_t;
|
||||||
|
|
||||||
/* This represents a decoded instruction. All decoded addresses are
|
/* This represents a decoded instruction. All decoded addresses are
|
||||||
|
@ -205,6 +220,10 @@ struct msp430_instruction {
|
||||||
msp430_amode_t dst_mode;
|
msp430_amode_t dst_mode;
|
||||||
address_t dst_addr;
|
address_t dst_addr;
|
||||||
msp430_reg_t dst_reg;
|
msp430_reg_t dst_reg;
|
||||||
|
|
||||||
|
int rep_index;
|
||||||
|
int rep_register;
|
||||||
|
int zero_carry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Decode a single instruction.
|
/* Decode a single instruction.
|
||||||
|
|
Loading…
Reference in New Issue