arm64: handle alias insn in a better way, and add support for MNEG. bug reported by Patroklos Argyroudis

This commit is contained in:
Nguyen Anh Quynh 2013-11-30 00:54:24 +08:00
parent 81d35e6105
commit 6b7abe3c81
8 changed files with 35 additions and 5 deletions

View File

@ -35,11 +35,21 @@ void MCInst_setOpcode(MCInst *inst, unsigned Op)
inst->Opcode = Op;
}
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
{
inst->OpcodePub = Op;
}
unsigned MCInst_getOpcode(const MCInst *inst)
{
return inst->Opcode;
}
unsigned MCInst_getOpcodePub(const MCInst *inst)
{
return inst->OpcodePub;
}
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
{
return &inst->Operands[i];

View File

@ -89,6 +89,7 @@ struct MCInst {
unsigned size; // number of operands
cs_insn pub_insn; // insn to be exposed to public
cs_mode mode; // to be referenced by internal code
unsigned OpcodePub;
};
void MCInst_Init(MCInst *inst);
@ -101,6 +102,10 @@ void MCInst_setOpcode(MCInst *inst, unsigned Op);
unsigned MCInst_getOpcode(const MCInst*);
void MCInst_setOpcodePub(MCInst *inst, unsigned Op);
unsigned MCInst_getOpcodePub(const MCInst*);
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i);
unsigned MCInst_getNumOperands(const MCInst *inst);

View File

@ -636,10 +636,11 @@ void AArch64_printInst(MCInst *MI, SStream *O, void *Info)
if (printAliasInstr(MI, O, Info)) {
char *mnem = strdup(O->buffer);
char *tab = strchr(mnem, '\t');
if (tab)
if (tab) {
*tab = '\0';
}
// reflect the new insn name (alias) in the opcode
MCInst_setOpcode(MI, AArch64_get_insn_id2(AArch64_map_insn(mnem)));
MCInst_setOpcodePub(MI, AArch64_map_insn(mnem));
free(mnem);
} else
AArch64InstPrinter_printInstruction(MI, O);

View File

@ -1854,6 +1854,7 @@ void AArch64_get_insn_id(cs_insn *insn, unsigned int id)
}
}
// given public insn id, return internal instruction ID
unsigned int AArch64_get_insn_id2(unsigned int id)
{
return insn_reverse_id(insns, ARR_SIZE(insns), id);
@ -2224,6 +2225,7 @@ char *AArch64_insn_name(unsigned int id)
return insn_name_maps[id].name;
}
// map instruction name to public instruction ID
arm64_reg AArch64_map_insn(char *name)
{
// map *S instructions back to original id
@ -2234,6 +2236,8 @@ arm64_reg AArch64_map_insn(char *name)
{ ARM64_INS_BIC, "BICS" },
{ ARM64_INS_SBC, "SBCS" },
{ ARM64_INS_SUB, "SUBS" },
// alias insn
{ ARM64_INS_MNEG, "MNEG" },
};
// NOTE: skip first NULL name in insn_name_maps

View File

@ -18,7 +18,7 @@ unsigned int AArch64_get_insn_id2(unsigned int id);
char *AArch64_insn_name(unsigned int id);
// map instruction name to instruction ID
// map instruction name to public instruction ID
arm64_reg AArch64_map_insn(char *name);
#endif

8
cs.c
View File

@ -170,8 +170,12 @@ static void fill_insn(cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mc
memcpy(insn, &mci->pub_insn, sizeof(*insn));
// map internal instruction opcode to public insn ID
if (handle->insn_id)
handle->insn_id(insn, MCInst_getOpcode(mci));
if (MCInst_getOpcodePub(mci))
MCInst_setOpcode(mci, MCInst_getOpcodePub(mci));
else {
if (handle->insn_id)
handle->insn_id(insn, MCInst_getOpcode(mci));
}
if (printer)
printer(insn->id, insn, buffer);

View File

@ -691,6 +691,10 @@ typedef enum arm64_insn {
ARM64_INS_USUBW,
ARM64_INS_UXTB,
ARM64_INS_UXTH,
// alias insn
ARM64_INS_MNEG,
ARM64_INS_MAX,
} arm64_insn;

View File

@ -131,6 +131,8 @@ static void test()
//#define ARM64_CODE "\x5f\x3f\x03\xd5" // clrex
//#define ARM64_CODE "\x5f\x3e\x03\xd5" // clrex #14
//#define ARM64_CODE "\x20\x00\x02\xab" // adds x0, x1, x2 (alias of adds x0, x1, x2, lsl #0)
//#define ARM64_CODE "\x20\xf4\x18\x9e" // fcvtzs x0, s1, #3
//#define ARM64_CODE "\x20\xfc\x02\x9b" // mneg x0, x1, x2
#define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b"
struct platform platforms[] = {