[ARM] Add alias support (#2209)
This commit is contained in:
parent
55818f2300
commit
d54934201c
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "Mapping.h"
|
||||
#include "capstone/capstone.h"
|
||||
#include "utils.h"
|
||||
|
||||
// create a cache for fast id lookup
|
||||
static unsigned short *make_id2insn(const insn_map *insns, unsigned int size)
|
||||
|
@ -343,6 +344,10 @@ void map_set_is_alias_insn(MCInst *MI, bool Val, uint64_t Alias) {
|
|||
MI->flat_insn->alias_id = Alias;
|
||||
}
|
||||
|
||||
static inline bool char_ends_mnem(const char c) {
|
||||
return (!c || c == ' ' || c == '\t');
|
||||
}
|
||||
|
||||
/// Sets an alternative id for some instruction.
|
||||
/// Or -1 if it fails.
|
||||
/// You must add (<ARCH>_INS_ALIAS_BEGIN + 1) to the id to get the real id.
|
||||
|
@ -354,7 +359,7 @@ void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_i
|
|||
int i = 0, j = 0;
|
||||
const char *asm_str_buf = O->buffer;
|
||||
// Skip spaces and tabs
|
||||
while (asm_str_buf[i] == ' ' || asm_str_buf[i] == '\t') {
|
||||
while (is_blank_char(asm_str_buf[i])) {
|
||||
if (!asm_str_buf[i]) {
|
||||
MI->flat_insn->alias_id = -1;
|
||||
return;
|
||||
|
@ -362,7 +367,7 @@ void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_i
|
|||
++i;
|
||||
}
|
||||
for (; j < sizeof(alias_mnem) - 1; ++j, ++i) {
|
||||
if (!asm_str_buf[i] || asm_str_buf[i] == ' ' || asm_str_buf[i] == '\t')
|
||||
if (char_ends_mnem(asm_str_buf[i]))
|
||||
break;
|
||||
alias_mnem[j] = asm_str_buf[i];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
{ ARM_INS_ALIAS_VMOV, "vmov" },
|
||||
{ ARM_INS_ALIAS_NOP, "nop" },
|
||||
{ ARM_INS_ALIAS_YIELD, "yield" },
|
||||
{ ARM_INS_ALIAS_WFE, "wfe" },
|
||||
{ ARM_INS_ALIAS_WFI, "wfi" },
|
||||
{ ARM_INS_ALIAS_SEV, "sev" },
|
||||
{ ARM_INS_ALIAS_SEVL, "sevl" },
|
||||
{ ARM_INS_ALIAS_ESB, "esb" },
|
||||
{ ARM_INS_ALIAS_CSDB, "csdb" },
|
||||
{ ARM_INS_ALIAS_CLRBHB, "clrbhb" },
|
||||
{ ARM_INS_ALIAS_PACBTI, "pacbti" },
|
||||
{ ARM_INS_ALIAS_BTI, "bti" },
|
||||
{ ARM_INS_ALIAS_PAC, "pac" },
|
||||
{ ARM_INS_ALIAS_AUT, "aut" },
|
||||
{ ARM_INS_ALIAS_SSBB, "ssbb" },
|
||||
{ ARM_INS_ALIAS_PSSBB, "pssbb" },
|
||||
{ ARM_INS_ALIAS_DFB, "dfb" },
|
||||
{ ARM_INS_ALIAS_CSETM, "csetm" },
|
||||
{ ARM_INS_ALIAS_CSET, "cset" },
|
||||
{ ARM_INS_ALIAS_CINC, "cinc" },
|
||||
{ ARM_INS_ALIAS_CINV, "cinv" },
|
||||
{ ARM_INS_ALIAS_CNEG, "cneg" },
|
||||
{ ARM_INS_ALIAS_VMLAV, "vmlav" },
|
||||
{ ARM_INS_ALIAS_VMLAVA, "vmlava" },
|
||||
{ ARM_INS_ALIAS_VRMLALVH, "vrmlalvh" },
|
||||
{ ARM_INS_ALIAS_VRMLALVHA, "vrmlalvha" },
|
||||
{ ARM_INS_ALIAS_VMLALV, "vmlalv" },
|
||||
{ ARM_INS_ALIAS_VMLALVA, "vmlalva" },
|
||||
{ ARM_INS_ALIAS_VBIC, "vbic" },
|
||||
{ ARM_INS_ALIAS_VEOR, "veor" },
|
||||
{ ARM_INS_ALIAS_VORN, "vorn" },
|
||||
{ ARM_INS_ALIAS_VORR, "vorr" },
|
||||
{ ARM_INS_ALIAS_VAND, "vand" },
|
||||
{ ARM_INS_ALIAS_VPSEL, "vpsel" },
|
||||
{ ARM_INS_ALIAS_ERET, "eret" },
|
|
@ -105,14 +105,17 @@ static void printRegName(SStream *OS, unsigned RegNo)
|
|||
|
||||
static void printInst(MCInst *MI, SStream *O, void *info)
|
||||
{
|
||||
bool isAlias = false;
|
||||
bool useAliasDetails = map_use_alias_details(MI);
|
||||
map_set_fill_detail_ops(MI, useAliasDetails);
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
MCRegisterInfo *MRI = (MCRegisterInfo *)info;
|
||||
MI->MRI = MRI;
|
||||
uint64_t Address = MI->address;
|
||||
|
||||
switch (Opcode) {
|
||||
// Check for MOVs and print canonical forms, instead.
|
||||
case ARM_MOVsr: {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
// FIXME: Thumb variants?
|
||||
MCOperand *MO3 = MCInst_getOperand(MI, (3));
|
||||
|
||||
|
@ -131,11 +134,15 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
SStream_concat0(O, ", ");
|
||||
printOperand(MI, 2, O);
|
||||
|
||||
;
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
}
|
||||
|
||||
case ARM_MOVsi: {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
// FIXME: Thumb variants?
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, (2));
|
||||
|
||||
|
@ -151,15 +158,20 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
printOperand(MI, 1, O);
|
||||
|
||||
if (ARM_AM_getSORegShOp(MCOperand_getImm(MO2)) == ARM_AM_rrx) {
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
}
|
||||
|
||||
SStream_concat(O, "%s%s%s%d", ", ", markup("<imm:"), "#",
|
||||
translateShiftImm(ARM_AM_getSORegOffset(
|
||||
MCOperand_getImm(MO2))));
|
||||
SStream_concat0(O, markup(">"));
|
||||
;
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
}
|
||||
|
||||
// A8.6.123 PUSH
|
||||
|
@ -167,6 +179,8 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
case ARM_t2STMDB_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP &&
|
||||
MCInst_getNumOperands(MI) > 5) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
// Should only print PUSH if there are at least two registers in the
|
||||
// list.
|
||||
SStream_concat0(O, "push");
|
||||
|
@ -176,20 +190,28 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
SStream_concat0(O, " ");
|
||||
|
||||
printRegisterList(MI, 4, O);
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
|
||||
case ARM_STR_PRE_IMM:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP &&
|
||||
MCOperand_getImm(MCInst_getOperand(MI, (3))) == -4) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
SStream_concat1(O, ' ');
|
||||
SStream_concat0(O, "push");
|
||||
printPredicateOperand(MI, 4, O);
|
||||
SStream_concat0(O, " {");
|
||||
printOperand(MI, 1, O);
|
||||
SStream_concat0(O, "}");
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
|
||||
|
@ -198,6 +220,8 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
case ARM_t2LDMIA_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP &&
|
||||
MCInst_getNumOperands(MI) > 5) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
// Should only print POP if there are at least two registers in the
|
||||
// list.
|
||||
SStream_concat0(O, "pop");
|
||||
|
@ -207,7 +231,10 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
SStream_concat0(O, " ");
|
||||
|
||||
printRegisterList(MI, 4, O);
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
|
||||
|
@ -215,24 +242,34 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
if ((MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP) &&
|
||||
((ARM_AM_getAM2Offset(MCOperand_getImm(
|
||||
MCInst_getOperand(MI, (4)))) == 4))) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
SStream_concat0(O, "pop");
|
||||
printPredicateOperand(MI, 5, O);
|
||||
SStream_concat0(O, " {");
|
||||
printOperand(MI, 0, O);
|
||||
SStream_concat0(O, "}");
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
case ARM_t2LDR_POST:
|
||||
if ((MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP) &&
|
||||
(Opcode == ARM_t2LDR_POST &&
|
||||
(MCOperand_getImm(MCInst_getOperand(MI, (3))) == 4))) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
SStream_concat0(O, "pop");
|
||||
printPredicateOperand(MI, 4, O);
|
||||
SStream_concat0(O, " {");
|
||||
printOperand(MI, 0, O);
|
||||
SStream_concat0(O, "}");
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
|
||||
|
@ -240,12 +277,17 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
case ARM_VSTMSDB_UPD:
|
||||
case ARM_VSTMDDB_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
SStream_concat0(O, "vpush");
|
||||
printPredicateOperand(MI, 2, O);
|
||||
SStream_concat0(O, " ");
|
||||
|
||||
printRegisterList(MI, 4, O);
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
|
||||
|
@ -253,17 +295,24 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
case ARM_VLDMSIA_UPD:
|
||||
case ARM_VLDMDIA_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP) {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
SStream_concat1(O, ' ');
|
||||
SStream_concat0(O, "vpop");
|
||||
printPredicateOperand(MI, 2, O);
|
||||
SStream_concat0(O, " ");
|
||||
|
||||
printRegisterList(MI, 4, O);
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
} else
|
||||
break;
|
||||
|
||||
case ARM_tLDMIA: {
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
bool Writeback = true;
|
||||
unsigned BaseReg = MCOperand_getReg(MCInst_getOperand(MI, (0)));
|
||||
for (unsigned i = 3; i < MCInst_getNumOperands(MI); ++i) {
|
||||
|
@ -283,7 +332,10 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
}
|
||||
SStream_concat0(O, ", ");
|
||||
printRegisterList(MI, 3, O);
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
}
|
||||
|
||||
// Combine 2 GPRs from disassember into a GPRPair to match with instr def.
|
||||
|
@ -297,7 +349,7 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
case ARM_LDAEXD:
|
||||
case ARM_STLEXD: {
|
||||
const MCRegisterClass *MRC =
|
||||
MCRegisterInfo_getRegClass(MRI, ARM_GPRRegClassID);
|
||||
MCRegisterInfo_getRegClass(MI->MRI, ARM_GPRRegClassID);
|
||||
bool isStore = Opcode == ARM_STREXD || Opcode == ARM_STLEXD;
|
||||
unsigned Reg = MCOperand_getReg(
|
||||
MCInst_getOperand(MI, isStore ? 1 : 0));
|
||||
|
@ -315,9 +367,9 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
MCOperand_CreateReg0(
|
||||
&NewMI,
|
||||
MCRegisterInfo_getMatchingSuperReg(
|
||||
MRI, Reg, ARM_gsub_0,
|
||||
MI->MRI, Reg, ARM_gsub_0,
|
||||
MCRegisterInfo_getRegClass(
|
||||
MRI, ARM_GPRPairRegClassID)));
|
||||
MI->MRI, ARM_GPRPairRegClassID)));
|
||||
|
||||
// Copy the rest operands into NewMI.
|
||||
for (unsigned i = isStore ? 3 : 2;
|
||||
|
@ -332,9 +384,18 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
}
|
||||
case ARM_TSB:
|
||||
case ARM_t2TSB:
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
|
||||
SStream_concat0(O, " tsb csync");
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
case ARM_t2DSB:
|
||||
isAlias = true;
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
|
||||
switch (MCOperand_getImm(MCInst_getOperand(MI, (0)))) {
|
||||
default:
|
||||
if (!printAliasInstr(MI, Address, O))
|
||||
|
@ -347,13 +408,25 @@ static void printInst(MCInst *MI, SStream *O, void *info)
|
|||
SStream_concat0(O, " pssbb");
|
||||
break;
|
||||
};
|
||||
return;
|
||||
if (useAliasDetails)
|
||||
return;
|
||||
else
|
||||
goto add_real_detail;
|
||||
}
|
||||
|
||||
if (!printAliasInstr(MI, Address, O))
|
||||
printInstruction(MI, Address, O);
|
||||
if (!isAlias)
|
||||
isAlias |= printAliasInstr(MI, Address, O);
|
||||
|
||||
;
|
||||
add_real_detail:
|
||||
MCInst_setIsAlias(MI, isAlias);
|
||||
if (!isAlias || !useAliasDetails) {
|
||||
map_set_fill_detail_ops(MI, !(isAlias && useAliasDetails));
|
||||
if (isAlias)
|
||||
SStream_Close(O);
|
||||
printInstruction(MI, Address, O);
|
||||
if (isAlias)
|
||||
SStream_Open(O);
|
||||
}
|
||||
}
|
||||
|
||||
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
|
|
|
@ -22,6 +22,24 @@
|
|||
#include "ARMInstPrinter.h"
|
||||
#include "ARMMapping.h"
|
||||
|
||||
static const name_map insn_alias_mnem_map[] = {
|
||||
#include "ARMGenCSAliasMnemMap.inc"
|
||||
{ ARM_INS_ALIAS_ASR, "asr" },
|
||||
{ ARM_INS_ALIAS_LSL, "lsl" },
|
||||
{ ARM_INS_ALIAS_LSR, "lsr" },
|
||||
{ ARM_INS_ALIAS_ROR, "ror" },
|
||||
{ ARM_INS_ALIAS_RRX, "rrx" },
|
||||
{ ARM_INS_ALIAS_UXTW, "uxtw" },
|
||||
{ ARM_INS_ALIAS_LDM, "ldm" },
|
||||
{ ARM_INS_ALIAS_POP, "pop" },
|
||||
{ ARM_INS_ALIAS_PUSH, "push" },
|
||||
{ ARM_INS_ALIAS_POPW, "pop.w" },
|
||||
{ ARM_INS_ALIAS_PUSHW, "push.w" },
|
||||
{ ARM_INS_ALIAS_VPOP, "vpop" },
|
||||
{ ARM_INS_ALIAS_VPUSH, "vpush" },
|
||||
{ ARM_INS_ALIAS_END, NULL }
|
||||
};
|
||||
|
||||
static const char *get_custom_reg_alias(unsigned reg)
|
||||
{
|
||||
switch (reg) {
|
||||
|
@ -165,6 +183,38 @@ static void ARM_add_cs_groups(MCInst *MI)
|
|||
}
|
||||
}
|
||||
|
||||
static void add_alias_details(MCInst *MI) {
|
||||
if (!detail_is_set(MI))
|
||||
return;
|
||||
switch (MI->flat_insn->alias_id) {
|
||||
default:
|
||||
return;
|
||||
case ARM_INS_ALIAS_POP:
|
||||
// Doesn't get set because memop is not printed.
|
||||
ARM_get_detail(MI)->post_index = true;
|
||||
// fallthrough
|
||||
case ARM_INS_ALIAS_PUSH:
|
||||
case ARM_INS_ALIAS_VPUSH:
|
||||
case ARM_INS_ALIAS_VPOP:
|
||||
map_add_implicit_read(MI, ARM_REG_SP);
|
||||
map_add_implicit_write(MI, ARM_REG_SP);
|
||||
break;
|
||||
case ARM_INS_ALIAS_LDM: {
|
||||
bool Writeback = true;
|
||||
unsigned BaseReg = MCInst_getOpVal(MI, 0);
|
||||
for (unsigned i = 3; i < MCInst_getNumOperands(MI); ++i) {
|
||||
if (MCInst_getOpVal(MI, i) == BaseReg)
|
||||
Writeback = false;
|
||||
}
|
||||
if (Writeback && detail_is_set(MI)) {
|
||||
ARM_get_detail(MI)->operands[0].access |= CS_AC_WRITE;
|
||||
MI->flat_insn->detail->writeback = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Some instructions have their operands not defined but
|
||||
/// hardcoded as string.
|
||||
/// Here we add those oprands to detail.
|
||||
|
@ -172,6 +222,12 @@ static void ARM_add_not_defined_ops(MCInst *MI)
|
|||
{
|
||||
if (!detail_is_set(MI))
|
||||
return;
|
||||
|
||||
if (MI->flat_insn->is_alias && MI->flat_insn->usesAliasDetails) {
|
||||
add_alias_details(MI);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
switch (Opcode) {
|
||||
default:
|
||||
|
@ -424,45 +480,6 @@ static void ARM_add_not_defined_ops(MCInst *MI)
|
|||
ARM_get_detail_op(MI, -1)->shift.value = translateShiftImm(
|
||||
ARM_AM_getSORegOffset(MCInst_getOpVal(MI, 2)));
|
||||
break;
|
||||
case ARM_STMDB_UPD:
|
||||
case ARM_t2STMDB_UPD:
|
||||
if (MCInst_getOpVal(MI, 0) == ARM_SP &&
|
||||
MCInst_getNumOperands(MI) > 5)
|
||||
MI->flat_insn->id = ARM_INS_PUSH;
|
||||
break;
|
||||
case ARM_STR_PRE_IMM:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP &&
|
||||
MCOperand_getImm(MCInst_getOperand(MI, (3))) == -4)
|
||||
MI->flat_insn->id = ARM_INS_PUSH;
|
||||
break;
|
||||
case ARM_LDMIA_UPD:
|
||||
case ARM_t2LDMIA_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP &&
|
||||
MCInst_getNumOperands(MI) > 5)
|
||||
MI->flat_insn->id = ARM_INS_POP;
|
||||
break;
|
||||
case ARM_LDR_POST_IMM:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP &&
|
||||
ARM_AM_getAM2Offset(
|
||||
MCOperand_getImm(MCInst_getOperand(MI, (4)))) == 4)
|
||||
MI->flat_insn->id = ARM_INS_POP;
|
||||
break;
|
||||
case ARM_t2LDR_POST:
|
||||
if ((MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP) &&
|
||||
(Opcode == ARM_t2LDR_POST &&
|
||||
(MCOperand_getImm(MCInst_getOperand(MI, (3))) == 4)))
|
||||
MI->flat_insn->id = ARM_INS_POP;
|
||||
break;
|
||||
case ARM_VSTMSDB_UPD:
|
||||
case ARM_VSTMDDB_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP)
|
||||
MI->flat_insn->id = ARM_INS_VPUSH;
|
||||
break;
|
||||
case ARM_VLDMSIA_UPD:
|
||||
case ARM_VLDMDIA_UPD:
|
||||
if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP)
|
||||
MI->flat_insn->id = ARM_INS_VPOP;
|
||||
break;
|
||||
case ARM_tLDMIA: {
|
||||
bool Writeback = true;
|
||||
unsigned BaseReg = MCInst_getOpVal(MI, 0);
|
||||
|
@ -477,13 +494,6 @@ static void ARM_add_not_defined_ops(MCInst *MI)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (MI->flat_insn->id == ARM_INS_PUSH ||
|
||||
MI->flat_insn->id == ARM_INS_POP ||
|
||||
MI->flat_insn->id == ARM_INS_VPUSH ||
|
||||
MI->flat_insn->id == ARM_INS_VPOP) {
|
||||
map_add_implicit_read(MI, ARM_REG_SP);
|
||||
map_add_implicit_write(MI, ARM_REG_SP);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unfortunately there is currently no way to easily extract
|
||||
|
@ -549,7 +559,12 @@ static void ARM_post_index_detection(MCInst *MI)
|
|||
/// and fills the detail information about the instruction and its operands.
|
||||
void ARM_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
|
||||
{
|
||||
MCRegisterInfo *MRI = (MCRegisterInfo *)info;
|
||||
MI->MRI = MRI;
|
||||
MI->fillDetailOps = detail_is_set(MI);
|
||||
MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
|
||||
ARM_LLVM_printInstruction(MI, O, info);
|
||||
map_set_alias_id(MI, O, insn_alias_mnem_map, ARR_SIZE(insn_alias_mnem_map) - 1);
|
||||
ARM_add_not_defined_ops(MI);
|
||||
ARM_post_index_detection(MI);
|
||||
ARM_add_cs_groups(MI);
|
||||
|
@ -580,10 +595,20 @@ static arm_reg arm_flag_regs[] = {
|
|||
const char *ARM_insn_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (id < ARM_INS_ALIAS_END && id > ARM_INS_ALIAS_BEGIN) {
|
||||
if (id - ARM_INS_ALIAS_BEGIN >= ARR_SIZE(insn_alias_mnem_map))
|
||||
return NULL;
|
||||
|
||||
return insn_alias_mnem_map[id - ARM_INS_ALIAS_BEGIN - 1].name;
|
||||
}
|
||||
if (id >= ARM_INS_ENDING)
|
||||
return NULL;
|
||||
|
||||
return insn_name_maps[id];
|
||||
if (id < ARR_SIZE(insn_name_maps))
|
||||
return insn_name_maps[id];
|
||||
|
||||
// not found
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
@ -1818,7 +1843,7 @@ static void add_cs_detail_template_2(MCInst *MI, arm_op_group op_group,
|
|||
void ARM_add_cs_detail(MCInst *MI, int /* arm_op_group */ op_group,
|
||||
va_list args)
|
||||
{
|
||||
if (!detail_is_set(MI))
|
||||
if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
|
||||
return;
|
||||
switch (op_group) {
|
||||
case ARM_OP_GROUP_RegImmShift: {
|
||||
|
|
|
@ -1179,10 +1179,57 @@ ARM_INS_CBZ = 930
|
|||
ARM_INS_POP = 931
|
||||
ARM_INS_PUSH = 932
|
||||
ARM_INS___BRKDIV0 = 933
|
||||
ARM_INS_VPOP = 934
|
||||
ARM_INS_VPUSH = 935
|
||||
ARM_INS_ENDING = 936
|
||||
ARM_INS_NOP = ARM_INS_HINT
|
||||
ARM_INS_ENDING = 934
|
||||
ARM_INS_ALIAS_BEGIN = 935
|
||||
ARM_INS_ALIAS_VMOV = 936
|
||||
ARM_INS_ALIAS_NOP = 937
|
||||
ARM_INS_ALIAS_YIELD = 938
|
||||
ARM_INS_ALIAS_WFE = 939
|
||||
ARM_INS_ALIAS_WFI = 940
|
||||
ARM_INS_ALIAS_SEV = 941
|
||||
ARM_INS_ALIAS_SEVL = 942
|
||||
ARM_INS_ALIAS_ESB = 943
|
||||
ARM_INS_ALIAS_CSDB = 944
|
||||
ARM_INS_ALIAS_CLRBHB = 945
|
||||
ARM_INS_ALIAS_PACBTI = 946
|
||||
ARM_INS_ALIAS_BTI = 947
|
||||
ARM_INS_ALIAS_PAC = 948
|
||||
ARM_INS_ALIAS_AUT = 949
|
||||
ARM_INS_ALIAS_SSBB = 950
|
||||
ARM_INS_ALIAS_PSSBB = 951
|
||||
ARM_INS_ALIAS_DFB = 952
|
||||
ARM_INS_ALIAS_CSETM = 953
|
||||
ARM_INS_ALIAS_CSET = 954
|
||||
ARM_INS_ALIAS_CINC = 955
|
||||
ARM_INS_ALIAS_CINV = 956
|
||||
ARM_INS_ALIAS_CNEG = 957
|
||||
ARM_INS_ALIAS_VMLAV = 958
|
||||
ARM_INS_ALIAS_VMLAVA = 959
|
||||
ARM_INS_ALIAS_VRMLALVH = 960
|
||||
ARM_INS_ALIAS_VRMLALVHA = 961
|
||||
ARM_INS_ALIAS_VMLALV = 962
|
||||
ARM_INS_ALIAS_VMLALVA = 963
|
||||
ARM_INS_ALIAS_VBIC = 964
|
||||
ARM_INS_ALIAS_VEOR = 965
|
||||
ARM_INS_ALIAS_VORN = 966
|
||||
ARM_INS_ALIAS_VORR = 967
|
||||
ARM_INS_ALIAS_VAND = 968
|
||||
ARM_INS_ALIAS_VPSEL = 969
|
||||
ARM_INS_ALIAS_ERET = 970
|
||||
ARM_INS_ALIAS_ASR = 971
|
||||
ARM_INS_ALIAS_LSL = 972
|
||||
ARM_INS_ALIAS_LSR = 973
|
||||
ARM_INS_ALIAS_ROR = 974
|
||||
ARM_INS_ALIAS_RRX = 975
|
||||
ARM_INS_ALIAS_UXTW = 976
|
||||
ARM_INS_ALIAS_LDM = 977
|
||||
ARM_INS_ALIAS_POP = 978
|
||||
ARM_INS_ALIAS_PUSH = 979
|
||||
ARM_INS_ALIAS_POPW = 980
|
||||
ARM_INS_ALIAS_PUSHW = 981
|
||||
ARM_INS_ALIAS_VPOP = 982
|
||||
ARM_INS_ALIAS_VPUSH = 983
|
||||
ARM_INS_ALIAS_END = 984
|
||||
|
||||
ARM_GRP_INVALID = 0
|
||||
ARM_GRP_JUMP = 1
|
||||
|
|
|
@ -1559,15 +1559,67 @@ typedef enum arm_insn {
|
|||
// clang-format on
|
||||
// generated content <ARMGenCSInsnEnum.inc> end
|
||||
|
||||
// Hard coded alias in LLVM, not defined as alias or instruction.
|
||||
// We give them a unique ID for convenience.
|
||||
ARM_INS_VPOP,
|
||||
ARM_INS_VPUSH,
|
||||
|
||||
ARM_INS_ENDING, // <-- mark the end of the list of instructions
|
||||
|
||||
// Alias
|
||||
ARM_INS_NOP = ARM_INS_HINT,
|
||||
ARM_INS_ALIAS_BEGIN,
|
||||
// generated content <ARMGenCSAliasEnum.inc> begin
|
||||
// clang-format off
|
||||
|
||||
ARM_INS_ALIAS_VMOV, // Real instr.: ARM_MVE_VORR
|
||||
ARM_INS_ALIAS_NOP, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_YIELD, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_WFE, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_WFI, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_SEV, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_SEVL, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_ESB, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_CSDB, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_CLRBHB, // Real instr.: ARM_HINT
|
||||
ARM_INS_ALIAS_PACBTI, // Real instr.: ARM_t2HINT
|
||||
ARM_INS_ALIAS_BTI, // Real instr.: ARM_t2HINT
|
||||
ARM_INS_ALIAS_PAC, // Real instr.: ARM_t2HINT
|
||||
ARM_INS_ALIAS_AUT, // Real instr.: ARM_t2HINT
|
||||
ARM_INS_ALIAS_SSBB, // Real instr.: ARM_t2DSB
|
||||
ARM_INS_ALIAS_PSSBB, // Real instr.: ARM_t2DSB
|
||||
ARM_INS_ALIAS_DFB, // Real instr.: ARM_t2DSB
|
||||
ARM_INS_ALIAS_CSETM, // Real instr.: ARM_t2CSINV
|
||||
ARM_INS_ALIAS_CSET, // Real instr.: ARM_t2CSINC
|
||||
ARM_INS_ALIAS_CINC, // Real instr.: ARM_t2CSINC
|
||||
ARM_INS_ALIAS_CINV, // Real instr.: ARM_t2CSINV
|
||||
ARM_INS_ALIAS_CNEG, // Real instr.: ARM_t2CSNEG
|
||||
ARM_INS_ALIAS_VMLAV, // Real instr.: ARM_MVE_VMLADAVs8
|
||||
ARM_INS_ALIAS_VMLAVA, // Real instr.: ARM_MVE_VMLADAVas8
|
||||
ARM_INS_ALIAS_VRMLALVH, // Real instr.: ARM_MVE_VRMLALDAVHs32
|
||||
ARM_INS_ALIAS_VRMLALVHA, // Real instr.: ARM_MVE_VRMLALDAVHas32
|
||||
ARM_INS_ALIAS_VMLALV, // Real instr.: ARM_MVE_VMLALDAVs16
|
||||
ARM_INS_ALIAS_VMLALVA, // Real instr.: ARM_MVE_VMLALDAVas16
|
||||
ARM_INS_ALIAS_VBIC, // Real instr.: ARM_MVE_VBIC
|
||||
ARM_INS_ALIAS_VEOR, // Real instr.: ARM_MVE_VEOR
|
||||
ARM_INS_ALIAS_VORN, // Real instr.: ARM_MVE_VORN
|
||||
ARM_INS_ALIAS_VORR, // Real instr.: ARM_MVE_VORR
|
||||
ARM_INS_ALIAS_VAND, // Real instr.: ARM_MVE_VAND
|
||||
ARM_INS_ALIAS_VPSEL, // Real instr.: ARM_MVE_VPSEL
|
||||
ARM_INS_ALIAS_ERET, // Real instr.: ARM_t2SUBS_PC_LR
|
||||
|
||||
// clang-format on
|
||||
// generated content <ARMGenCSAliasEnum.inc> end
|
||||
|
||||
// Hardcoded in LLVM printer
|
||||
ARM_INS_ALIAS_ASR,
|
||||
ARM_INS_ALIAS_LSL,
|
||||
ARM_INS_ALIAS_LSR,
|
||||
ARM_INS_ALIAS_ROR,
|
||||
ARM_INS_ALIAS_RRX,
|
||||
ARM_INS_ALIAS_UXTW,
|
||||
ARM_INS_ALIAS_LDM,
|
||||
ARM_INS_ALIAS_POP,
|
||||
ARM_INS_ALIAS_PUSH,
|
||||
ARM_INS_ALIAS_POPW,
|
||||
ARM_INS_ALIAS_PUSHW,
|
||||
ARM_INS_ALIAS_VPOP,
|
||||
ARM_INS_ALIAS_VPUSH,
|
||||
|
||||
ARM_INS_ALIAS_END,
|
||||
} arm_insn;
|
||||
|
||||
/// Group of ARM instructions
|
||||
|
|
5
utils.h
5
utils.h
|
@ -42,5 +42,8 @@ uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes);
|
|||
|
||||
void append_to_str_lower(char *str, size_t str_size, const char *src);
|
||||
static inline bool strings_match(const char *str0, const char *str1) { return strcmp(str0, str1) == 0; }
|
||||
#endif
|
||||
|
||||
static inline bool is_blank_char(const char c) {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue