dis: tidy up main decode function, bug fixes.

This commit is contained in:
Daniel Beer 2010-08-10 15:57:25 +12:00
parent 5fe3be27d2
commit c4ce4c7325
2 changed files with 40 additions and 39 deletions

71
dis.c
View File

@ -217,6 +217,23 @@ static int decode_13xx(const uint8_t *code, address_t offset,
return 4; return 4;
} }
static int decode_14xx(const uint8_t *code, address_t offset,
address_t size, struct msp430_instruction *insn)
{
uint16_t op = (code[1] << 8) | code[0];
/* PUSHM/POPM */
insn->itype = MSP430_ITYPE_SINGLE;
insn->op = op & 0xfe00;
insn->dst_mode = MSP430_AMODE_REGISTER;
insn->dst_reg = op & 0xf;
insn->rep_index = (op >> 4) & 0xf;
insn->dsize = (op & 0x0100) ?
MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD;
return 2;
}
/* Decode a single-operand instruction. /* Decode a single-operand instruction.
* *
* 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
@ -228,6 +245,7 @@ static int decode_single(const uint8_t *code, address_t offset,
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->itype = MSP430_ITYPE_SINGLE;
insn->op = op & 0xff80; insn->op = op & 0xff80;
insn->dsize = (op & 0x0400) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD; insn->dsize = (op & 0x0400) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD;
@ -282,6 +300,7 @@ static int decode_double(const uint8_t *code, address_t offset,
int need_dst = 0; int need_dst = 0;
int ret = 2; int ret = 2;
insn->itype = MSP430_ITYPE_DOUBLE;
insn->op = op & 0xf000; insn->op = op & 0xf000;
insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD; insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD;
@ -373,6 +392,7 @@ static int decode_jump(const uint8_t *code, address_t offset, address_t len,
tgtrel -= 0x400; tgtrel -= 0x400;
insn->op = op & 0xfc00; insn->op = op & 0xfc00;
insn->itype = MSP430_ITYPE_JUMP;
insn->dst_addr = offset + 2 + tgtrel * 2; insn->dst_addr = offset + 2 + tgtrel * 2;
insn->dst_mode = MSP430_AMODE_SYMBOLIC; insn->dst_mode = MSP430_AMODE_SYMBOLIC;
insn->dst_reg = MSP430_REG_PC; insn->dst_reg = MSP430_REG_PC;
@ -610,17 +630,15 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
return -1; return -1;
op = (code[1] << 8) | code[0]; op = (code[1] << 8) | code[0];
if ((op & 0xff00) >= 0x4000) { if ((op & 0xf000) >= 0x4000)
insn->itype = MSP430_ITYPE_DOUBLE;
ret = decode_double(code, offset, len, insn); ret = decode_double(code, offset, len, insn);
insn->op |= EXTENSION_BIT; else if ((op & 0xf000) == 0x1000 && (op & 0xfc00) < 0x1280)
} else if ((op & 0xf000) == 0x1000 && (op & 0xfc00) < 0x1280) {
insn->itype = MSP430_ITYPE_SINGLE;
ret = decode_single(code, offset, len, insn); ret = decode_single(code, offset, len, insn);
insn->op |= EXTENSION_BIT; else
} else {
return -1; return -1;
}
insn->op |= EXTENSION_BIT;
ret += 2;
if (insn->dst_mode == MSP430_AMODE_REGISTER && if (insn->dst_mode == MSP430_AMODE_REGISTER &&
(insn->itype == MSP430_ITYPE_SINGLE || (insn->itype == MSP430_ITYPE_SINGLE ||
@ -637,41 +655,24 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
insn->src_addr |= ((ex_word >> 6) & 0xf) << 16; insn->src_addr |= ((ex_word >> 6) & 0xf) << 16;
} }
if (ex_word & 0x40) { if (!(ex_word & 0x40))
if (insn->dsize == MSP430_DSIZE_BYTE) insn->dsize |= 2;
insn->dsize = MSP430_DSIZE_AWORD;
else
insn->dsize = MSP430_DSIZE_UNKNOWN;
}
} else { } else {
if ((op & 0xf000) == 0x0000) { if ((op & 0xf000) == 0x0000)
ret = decode_00xx(code, offset, len, insn); ret = decode_00xx(code, offset, len, insn);
} else if ((op & 0xfc00) == 0x1400) { else if ((op & 0xfc00) == 0x1400)
/* PUSHM/POPM */ ret = decode_14xx(code, offset, len, insn);
insn->itype = MSP430_ITYPE_SINGLE; else if ((op & 0xff00) == 0x1300)
insn->op = op & 0xfe00;
insn->dst_mode = MSP430_AMODE_REGISTER;
insn->dst_reg = op & 0xf;
insn->rep_index = (op >> 4) & 0xf;
insn->dsize = (op & 0x0100) ?
MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD;
ret = 2;
} else if ((op & 0xff00) == 0x1300) {
ret = decode_13xx(code, offset, len, insn); ret = decode_13xx(code, offset, len, insn);
} else if ((op & 0xf000) == 0x1000) { else if ((op & 0xf000) == 0x1000)
insn->itype = MSP430_ITYPE_SINGLE;
ret = decode_single(code, offset, len, insn); ret = decode_single(code, offset, len, insn);
} else if ((op & 0xff00) >= 0x2000 && else if ((op & 0xf000) >= 0x2000 && (op & 0xf000) < 0x4000)
(op & 0xff00) < 0x4000) {
insn->itype = MSP430_ITYPE_JUMP;
ret = decode_jump(code, offset, len, insn); ret = decode_jump(code, offset, len, insn);
} else if ((op & 0xf000) >= 0x4000) { else if ((op & 0xf000) >= 0x4000)
insn->itype = MSP430_ITYPE_DOUBLE;
ret = decode_double(code, offset, len, insn); ret = decode_double(code, offset, len, insn);
} else { else
return -1; return -1;
} }
}
/* Interpret "emulated" instructions, constant generation, and /* Interpret "emulated" instructions, constant generation, and
* trim data sizes. * trim data sizes.

6
dis.h
View File

@ -108,9 +108,9 @@ typedef enum {
*/ */
typedef enum { typedef enum {
MSP430_DSIZE_WORD = 0, MSP430_DSIZE_WORD = 0,
MSP430_DSIZE_BYTE, MSP430_DSIZE_BYTE = 1,
MSP430_DSIZE_AWORD, MSP430_DSIZE_UNKNOWN = 2,
MSP430_DSIZE_UNKNOWN MSP430_DSIZE_AWORD = 3,
} msp430_dsize_t; } msp430_dsize_t;
/* MSP430 operations. /* MSP430 operations.