Path: blob/master/libs/capstone/arch/ARM/ARMInstPrinter.c
4394 views
//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//1//2// The LLVM Compiler Infrastructure3//4// This file is distributed under the University of Illinois Open Source5// License. See LICENSE.TXT for details.6//7//===----------------------------------------------------------------------===//8//9// This class prints an ARM MCInst to a .s file.10//11//===----------------------------------------------------------------------===//1213/* Capstone Disassembly Engine */14/* By Nguyen Anh Quynh <[email protected]>, 2013-2019 */1516#ifdef CAPSTONE_HAS_ARM1718#include <stdio.h> // DEBUG19#include <stdlib.h>20#include <string.h>21#include <capstone/platform.h>2223#include "ARMInstPrinter.h"24#include "ARMAddressingModes.h"25#include "ARMBaseInfo.h"26#include "ARMDisassembler.h"27#include "../../MCInst.h"28#include "../../SStream.h"29#include "../../MCRegisterInfo.h"30#include "../../utils.h"31#include "ARMMapping.h"3233#define GET_SUBTARGETINFO_ENUM34#include "ARMGenSubtargetInfo.inc"3536#include "ARMGenSystemRegister.inc"3738static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo);3940// Autogenerated by tblgen.41static void printInstruction(MCInst *MI, SStream *O);42static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);43static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O);44static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O);4546static void printAddrModeTBB(MCInst *MI, unsigned OpNum, SStream *O);47static void printAddrModeTBH(MCInst *MI, unsigned OpNum, SStream *O);48static void printAddrMode2Operand(MCInst *MI, unsigned OpNum, SStream *O);49static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned OpNum, SStream *O);50static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);51static void printAddrMode3Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);52static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);53static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O, bool AlwaysPrintImm0);54static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O);55static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O);56static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O);57static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);58static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O);59static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O);60static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);6162static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O);63static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O);64static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O);65static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O);66static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O);67static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned);68static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O);69static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O);70static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O);71static void printThumbAddrModeRROperand(MCInst *MI, unsigned OpNum, SStream *O);72static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale);73static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned OpNum, SStream *O);74static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned OpNum, SStream *O);75static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned OpNum, SStream *O);76static void printThumbAddrModeSPOperand(MCInst *MI, unsigned OpNum, SStream *O);77static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O);78static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);79static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);80static void printT2AddrModeImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);81static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O);82static void printT2AddrModeImm8OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);83static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);84static void printT2AddrModeSoRegOperand(MCInst *MI, unsigned OpNum, SStream *O);85static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O);86static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O);87static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O);88static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O);89static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);90static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);91static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O);92static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O);93static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O);94static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O);95static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O);96static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O);97static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O);98static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);99static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O);100static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O);101static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O);102static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O);103static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O);104static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O);105static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O);106static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O);107static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O);108static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O);109static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O);110static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O);111static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O);112static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O);113static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O);114static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O);115static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);116static void printVectorListThreeSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);117static void printVectorListFourSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);118static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O);119static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O);120static void printBankedRegOperand(MCInst *MI, unsigned OpNum, SStream *O);121static void printModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);122123static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);124static void printTraceSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);125static void printComplexRotationOp(MCInst *MI, unsigned OpNo, SStream *O, int64_t Angle, int64_t Remainder);126static void printAddrMode5FP16Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);127128129#ifndef CAPSTONE_DIET130// copy & normalize access info131static uint8_t get_op_access(cs_struct *h, unsigned int id, unsigned int index)132{133const uint8_t *arr = ARM_get_op_access(h, id);134135if (!arr || arr[index] == CS_AC_IGNORE)136return 0;137138return arr[index];139}140#endif141142static void set_mem_access(MCInst *MI, bool status)143{144if (MI->csh->detail != CS_OPT_ON)145return;146147MI->csh->doing_mem = status;148if (status) {149#ifndef CAPSTONE_DIET150uint8_t access;151#endif152153MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;154MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_INVALID;155MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;156MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;157MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;158159#ifndef CAPSTONE_DIET160access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);161MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;162MI->ac_idx++;163#endif164} else {165// done, create the next operand slot166MI->flat_insn->detail->arm.op_count++;167}168}169170static void op_addImm(MCInst *MI, int v)171{172if (MI->csh->detail) {173MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;174MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;175MI->flat_insn->detail->arm.op_count++;176}177}178179#define GET_INSTRINFO_ENUM180#include "ARMGenInstrInfo.inc"181182static void printCustomAliasOperand(MCInst *MI,183unsigned OpIdx, unsigned PrintMethodIdx, SStream *OS);184185#define PRINT_ALIAS_INSTR186#include "ARMGenAsmWriter.inc"187#include "ARMGenRegisterName.inc"188#include "ARMGenRegisterName_digit.inc"189190void ARM_getRegName(cs_struct *handle, int value)191{192if (value == CS_OPT_SYNTAX_NOREGNAME) {193handle->get_regname = getRegisterName_digit;194handle->reg_name = ARM_reg_name2;195} else {196handle->get_regname = getRegisterName;197handle->reg_name = ARM_reg_name;198}199}200201/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.202///203/// getSORegOffset returns an integer from 0-31, representing '32' as 0.204static unsigned translateShiftImm(unsigned imm)205{206// lsr #32 and asr #32 exist, but should be encoded as a 0.207//assert((imm & ~0x1f) == 0 && "Invalid shift encoding");208if (imm == 0)209return 32;210return imm;211}212213/// Prints the shift value with an immediate value.214static void printRegImmShift(MCInst *MI, SStream *O, ARM_AM_ShiftOpc ShOpc, unsigned ShImm)215{216if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))217return;218219SStream_concat0(O, ", ");220221//assert (!(ShOpc == ARM_AM_ror && !ShImm) && "Cannot have ror #0");222SStream_concat0(O, ARM_AM_getShiftOpcStr(ShOpc));223224if (MI->csh->detail) {225if (MI->csh->doing_mem)226MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)ShOpc;227else228MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = (arm_shifter)ShOpc;229}230231if (ShOpc != ARM_AM_rrx) {232SStream_concat0(O, " ");233SStream_concat(O, "#%u", translateShiftImm(ShImm));234if (MI->csh->detail) {235if (MI->csh->doing_mem)236MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = translateShiftImm(ShImm);237else238MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = translateShiftImm(ShImm);239}240}241}242243static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo)244{245#ifndef CAPSTONE_DIET246SStream_concat0(OS, h->get_regname(RegNo));247#endif248}249250// TODO251static const name_map insn_update_flgs[] = {252{ ARM_INS_CMN, "cmn" },253{ ARM_INS_CMP, "cmp" },254{ ARM_INS_TEQ, "teq" },255{ ARM_INS_TST, "tst" },256257{ ARM_INS_ADC, "adcs" },258{ ARM_INS_ADD, "adds" },259{ ARM_INS_AND, "ands" },260{ ARM_INS_ASR, "asrs" },261{ ARM_INS_BIC, "bics" },262{ ARM_INS_EOR, "eors" },263{ ARM_INS_LSL, "lsls" },264{ ARM_INS_LSR, "lsrs" },265{ ARM_INS_MLA, "mlas" },266{ ARM_INS_MOV, "movs" },267{ ARM_INS_MUL, "muls" },268{ ARM_INS_MVN, "mvns" },269{ ARM_INS_ORN, "orns" },270{ ARM_INS_ORR, "orrs" },271{ ARM_INS_ROR, "rors" },272{ ARM_INS_RRX, "rrxs" },273{ ARM_INS_RSB, "rsbs" },274{ ARM_INS_RSC, "rscs" },275{ ARM_INS_SBC, "sbcs" },276{ ARM_INS_SMLAL, "smlals" },277{ ARM_INS_SMULL, "smulls" },278{ ARM_INS_SUB, "subs" },279{ ARM_INS_UMLAL, "umlals" },280{ ARM_INS_UMULL, "umulls" },281282{ ARM_INS_UADD8, "uadd8" },283};284285void ARM_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)286{287if (((cs_struct *)ud)->detail != CS_OPT_ON)288return;289290// check if this insn requests write-back291if (mci->writeback || (strrchr(insn_asm, '!')) != NULL) {292insn->detail->arm.writeback = true;293} else if (mci->csh->mode & CS_MODE_THUMB) {294// handle some special instructions with writeback295//printf(">> Opcode = %u\n", mci->Opcode);296switch(mci->Opcode) {297default:298break;299case ARM_t2LDC2L_PRE:300case ARM_t2LDC2_PRE:301case ARM_t2LDCL_PRE:302case ARM_t2LDC_PRE:303304case ARM_t2LDRB_PRE:305case ARM_t2LDRD_PRE:306case ARM_t2LDRH_PRE:307case ARM_t2LDRSB_PRE:308case ARM_t2LDRSH_PRE:309case ARM_t2LDR_PRE:310311case ARM_t2STC2L_PRE:312case ARM_t2STC2_PRE:313case ARM_t2STCL_PRE:314case ARM_t2STC_PRE:315316case ARM_t2STRB_PRE:317case ARM_t2STRD_PRE:318case ARM_t2STRH_PRE:319case ARM_t2STR_PRE:320insn->detail->arm.writeback = true;321break;322case ARM_t2LDC2L_POST:323case ARM_t2LDC2_POST:324case ARM_t2LDCL_POST:325case ARM_t2LDC_POST:326327case ARM_t2LDRB_POST:328case ARM_t2LDRD_POST:329case ARM_t2LDRH_POST:330case ARM_t2LDRSB_POST:331case ARM_t2LDRSH_POST:332case ARM_t2LDR_POST:333334case ARM_t2STC2L_POST:335case ARM_t2STC2_POST:336case ARM_t2STCL_POST:337case ARM_t2STC_POST:338339case ARM_t2STRB_POST:340case ARM_t2STRD_POST:341case ARM_t2STRH_POST:342case ARM_t2STR_POST:343insn->detail->arm.writeback = true;344insn->detail->arm.post_index = true;345break;346}347} else { // ARM mode348// handle some special instructions with writeback349//printf(">> Opcode = %u\n", mci->Opcode);350switch(mci->Opcode) {351default:352break;353case ARM_LDC2L_PRE:354case ARM_LDC2_PRE:355case ARM_LDCL_PRE:356case ARM_LDC_PRE:357358case ARM_LDRD_PRE:359case ARM_LDRH_PRE:360case ARM_LDRSB_PRE:361case ARM_LDRSH_PRE:362363case ARM_STC2L_PRE:364case ARM_STC2_PRE:365case ARM_STCL_PRE:366case ARM_STC_PRE:367368case ARM_STRD_PRE:369case ARM_STRH_PRE:370insn->detail->arm.writeback = true;371break;372case ARM_LDC2L_POST:373case ARM_LDC2_POST:374case ARM_LDCL_POST:375case ARM_LDC_POST:376377case ARM_LDRBT_POST:378case ARM_LDRD_POST:379case ARM_LDRH_POST:380case ARM_LDRSB_POST:381case ARM_LDRSH_POST:382383case ARM_STC2L_POST:384case ARM_STC2_POST:385case ARM_STCL_POST:386case ARM_STC_POST:387388case ARM_STRBT_POST:389case ARM_STRD_POST:390case ARM_STRH_POST:391392case ARM_LDRB_POST_IMM:393case ARM_LDR_POST_IMM:394case ARM_LDR_POST_REG:395case ARM_STRB_POST_IMM:396397case ARM_STR_POST_IMM:398case ARM_STR_POST_REG:399insn->detail->arm.writeback = true;400insn->detail->arm.post_index = true;401break;402}403}404405// check if this insn requests update flags406if (insn->detail->arm.update_flags == false) {407// some insn still update flags, regardless of tabgen info408unsigned int i, j;409410for (i = 0; i < ARR_SIZE(insn_update_flgs); i++) {411if (insn->id == insn_update_flgs[i].id &&412!strncmp(insn_asm, insn_update_flgs[i].name,413strlen(insn_update_flgs[i].name))) {414insn->detail->arm.update_flags = true;415// we have to update regs_write array as well416for (j = 0; j < ARR_SIZE(insn->detail->regs_write); j++) {417if (insn->detail->regs_write[j] == 0) {418insn->detail->regs_write[j] = ARM_REG_CPSR;419break;420}421}422break;423}424}425}426427// instruction should not have invalid CC428if (insn->detail->arm.cc == ARM_CC_INVALID) {429insn->detail->arm.cc = ARM_CC_AL;430}431432// manual fix for some special instructions433// printf(">>> id: %u, mcid: %u\n", insn->id, mci->Opcode);434switch(mci->Opcode) {435default:436break;437case ARM_MOVPCLR:438insn->detail->arm.operands[0].type = ARM_OP_REG;439insn->detail->arm.operands[0].reg = ARM_REG_PC;440insn->detail->arm.operands[0].access = CS_AC_WRITE;441insn->detail->arm.operands[1].type = ARM_OP_REG;442insn->detail->arm.operands[1].reg = ARM_REG_LR;443insn->detail->arm.operands[1].access = CS_AC_READ;444insn->detail->arm.op_count = 2;445break;446}447}448449void ARM_printInst(MCInst *MI, SStream *O, void *Info)450{451MCRegisterInfo *MRI = (MCRegisterInfo *)Info;452unsigned Opcode = MCInst_getOpcode(MI), tmp, i;453454//printf(">>> Opcode = %u\n", Opcode);455switch (Opcode) {456// Check for MOVs and print canonical forms, instead.457case ARM_MOVsr: {458// FIXME: Thumb variants?459unsigned int opc;460MCOperand *Dst = MCInst_getOperand(MI, 0);461MCOperand *MO1 = MCInst_getOperand(MI, 1);462MCOperand *MO2 = MCInst_getOperand(MI, 2);463MCOperand *MO3 = MCInst_getOperand(MI, 3);464465opc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));466SStream_concat0(O, ARM_AM_getShiftOpcStr(opc));467468switch (opc) {469default: break;470case ARM_AM_asr:471MCInst_setOpcodePub(MI, ARM_INS_ASR);472break;473case ARM_AM_lsl:474MCInst_setOpcodePub(MI, ARM_INS_LSL);475break;476case ARM_AM_lsr:477MCInst_setOpcodePub(MI, ARM_INS_LSR);478break;479case ARM_AM_ror:480MCInst_setOpcodePub(MI, ARM_INS_ROR);481break;482case ARM_AM_rrx:483MCInst_setOpcodePub(MI, ARM_INS_RRX);484break;485}486487printSBitModifierOperand(MI, 6, O);488printPredicateOperand(MI, 4, O);489490SStream_concat0(O, "\t");491printRegName(MI->csh, O, MCOperand_getReg(Dst));492493if (MI->csh->detail) {494MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;495MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);496MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;497MI->flat_insn->detail->arm.op_count++;498}499500SStream_concat0(O, ", ");501printRegName(MI->csh, O, MCOperand_getReg(MO1));502503if (MI->csh->detail) {504MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;505MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);506MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;507MI->flat_insn->detail->arm.op_count++;508}509510SStream_concat0(O, ", ");511printRegName(MI->csh, O, MCOperand_getReg(MO2));512513if (MI->csh->detail) {514MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;515MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO2);516MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;517MI->flat_insn->detail->arm.op_count++;518}519520return;521}522523case ARM_MOVsi: {524// FIXME: Thumb variants?525unsigned int opc;526MCOperand *Dst = MCInst_getOperand(MI, 0);527MCOperand *MO1 = MCInst_getOperand(MI, 1);528MCOperand *MO2 = MCInst_getOperand(MI, 2);529530opc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2));531SStream_concat0(O, ARM_AM_getShiftOpcStr(opc));532533switch(opc) {534default:535break;536case ARM_AM_asr:537MCInst_setOpcodePub(MI, ARM_INS_ASR);538break;539case ARM_AM_lsl:540MCInst_setOpcodePub(MI, ARM_INS_LSL);541break;542case ARM_AM_lsr:543MCInst_setOpcodePub(MI, ARM_INS_LSR);544break;545case ARM_AM_ror:546MCInst_setOpcodePub(MI, ARM_INS_ROR);547break;548case ARM_AM_rrx:549MCInst_setOpcodePub(MI, ARM_INS_RRX);550break;551}552553printSBitModifierOperand(MI, 5, O);554printPredicateOperand(MI, 3, O);555556SStream_concat0(O, "\t");557printRegName(MI->csh, O, MCOperand_getReg(Dst));558559if (MI->csh->detail) {560MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;561MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);562MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;563MI->flat_insn->detail->arm.op_count++;564}565566SStream_concat0(O, ", ");567printRegName(MI->csh, O, MCOperand_getReg(MO1));568if (MI->csh->detail) {569MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;570MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);571MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;572MI->flat_insn->detail->arm.op_count++;573}574575if (opc == ARM_AM_rrx) {576//printAnnotation(O, Annot);577return;578}579580SStream_concat0(O, ", ");581tmp = translateShiftImm(getSORegOffset((unsigned int)MCOperand_getImm(MO2)));582printUInt32Bang(O, tmp);583if (MI->csh->detail) {584MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type =585(arm_shifter)opc;586MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;587}588589return;590}591592// A8.6.123 PUSH593case ARM_STMDB_UPD:594case ARM_t2STMDB_UPD:595if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&596MCInst_getNumOperands(MI) > 5) {597// Should only print PUSH if there are at least two registers in the list.598SStream_concat0(O, "push");599MCInst_setOpcodePub(MI, ARM_INS_PUSH);600printPredicateOperand(MI, 2, O);601602if (Opcode == ARM_t2STMDB_UPD)603SStream_concat0(O, ".w");604605SStream_concat0(O, "\t");606607if (MI->csh->detail) {608MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;609MI->flat_insn->detail->regs_read_count++;610MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;611MI->flat_insn->detail->regs_write_count++;612}613614printRegisterList(MI, 4, O);615return;616} else617break;618619case ARM_STR_PRE_IMM:620if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP &&621MCOperand_getImm(MCInst_getOperand(MI, 3)) == -4) {622SStream_concat0(O, "push");623MCInst_setOpcodePub(MI, ARM_INS_PUSH);624625printPredicateOperand(MI, 4, O);626627SStream_concat0(O, "\t{");628629printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 1)));630631if (MI->csh->detail) {632#ifndef CAPSTONE_DIET633uint8_t access;634#endif635MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;636MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 1));637#ifndef CAPSTONE_DIET638access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);639MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;640MI->ac_idx++;641#endif642MI->flat_insn->detail->arm.op_count++;643}644645SStream_concat0(O, "}");646647return;648} else649break;650651// A8.6.122 POP652case ARM_LDMIA_UPD:653case ARM_t2LDMIA_UPD:654if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&655MCInst_getNumOperands(MI) > 5) {656// Should only print POP if there are at least two registers in the list.657SStream_concat0(O, "pop");658MCInst_setOpcodePub(MI, ARM_INS_POP);659660printPredicateOperand(MI, 2, O);661if (Opcode == ARM_t2LDMIA_UPD)662SStream_concat0(O, ".w");663664SStream_concat0(O, "\t");665666// unlike LDM, POP only write to registers, so skip the 1st access code667MI->ac_idx = 1;668if (MI->csh->detail) {669MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;670MI->flat_insn->detail->regs_read_count++;671MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;672MI->flat_insn->detail->regs_write_count++;673}674675printRegisterList(MI, 4, O);676677return;678}679break;680681case ARM_LDR_POST_IMM:682if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP) {683MCOperand *MO2 = MCInst_getOperand(MI, 4);684685if (getAM2Offset((unsigned int)MCOperand_getImm(MO2)) == 4) {686SStream_concat0(O, "pop");687MCInst_setOpcodePub(MI, ARM_INS_POP);688printPredicateOperand(MI, 5, O);689SStream_concat0(O, "\t{");690691printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 0)));692693if (MI->csh->detail) {694MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;695MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));696MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;697MI->flat_insn->detail->arm.op_count++;698// this instruction implicitly read/write SP register699MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;700MI->flat_insn->detail->regs_read_count++;701MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;702MI->flat_insn->detail->regs_write_count++;703}704SStream_concat0(O, "}");705return;706}707}708break;709710// A8.6.355 VPUSH711case ARM_VSTMSDB_UPD:712case ARM_VSTMDDB_UPD:713if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {714SStream_concat0(O, "vpush");715MCInst_setOpcodePub(MI, ARM_INS_VPUSH);716printPredicateOperand(MI, 2, O);717SStream_concat0(O, "\t");718printRegisterList(MI, 4, O);719return;720}721break;722723// A8.6.354 VPOP724case ARM_VLDMSIA_UPD:725case ARM_VLDMDIA_UPD:726if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {727SStream_concat0(O, "vpop");728MCInst_setOpcodePub(MI, ARM_INS_VPOP);729printPredicateOperand(MI, 2, O);730SStream_concat0(O, "\t");731printRegisterList(MI, 4, O);732return;733}734break;735736case ARM_tLDMIA: {737bool Writeback = true;738unsigned BaseReg = MCOperand_getReg(MCInst_getOperand(MI, 0));739unsigned i;740741for (i = 3; i < MCInst_getNumOperands(MI); ++i) {742if (MCOperand_getReg(MCInst_getOperand(MI, i)) == BaseReg)743Writeback = false;744}745746SStream_concat0(O, "ldm");747MCInst_setOpcodePub(MI, ARM_INS_LDM);748749printPredicateOperand(MI, 1, O);750SStream_concat0(O, "\t");751printRegName(MI->csh, O, BaseReg);752if (MI->csh->detail) {753MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;754MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = BaseReg;755MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ | CS_AC_WRITE;756MI->flat_insn->detail->arm.op_count++;757}758759if (Writeback) {760MI->writeback = true;761SStream_concat0(O, "!");762}763764SStream_concat0(O, ", ");765printRegisterList(MI, 3, O);766return;767}768769// Combine 2 GPRs from disassember into a GPRPair to match with instr def.770// ldrexd/strexd require even/odd GPR pair. To enforce this constraint,771// a single GPRPair reg operand is used in the .td file to replace the two772// GPRs. However, when decoding them, the two GRPs cannot be automatically773// expressed as a GPRPair, so we have to manually merge them.774// FIXME: We would really like to be able to tablegen'erate this.775case ARM_LDREXD:776case ARM_STREXD:777case ARM_LDAEXD:778case ARM_STLEXD: {779const MCRegisterClass *MRC = MCRegisterInfo_getRegClass(MRI, ARM_GPRRegClassID);780bool isStore = Opcode == ARM_STREXD || Opcode == ARM_STLEXD;781unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, isStore ? 1 : 0));782783if (MCRegisterClass_contains(MRC, Reg)) {784MCInst NewMI;785786MCInst_Init(&NewMI);787MCInst_setOpcode(&NewMI, Opcode);788789if (isStore)790MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, 0));791792MCOperand_CreateReg0(&NewMI, MCRegisterInfo_getMatchingSuperReg(MRI, Reg, ARM_gsub_0,793MCRegisterInfo_getRegClass(MRI, ARM_GPRPairRegClassID)));794795// Copy the rest operands into NewMI.796for(i = isStore ? 3 : 2; i < MCInst_getNumOperands(MI); ++i)797MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, i));798799printInstruction(&NewMI, O);800return;801}802break;803}804805case ARM_TSB:806case ARM_t2TSB:807SStream_concat0(O, "tsb\tcsync");808MCInst_setOpcodePub(MI, ARM_INS_TSB);809// TODO: add csync to operands[]?810return;811}812813MI->MRI = MRI;814815if (!printAliasInstr(MI, O)) {816printInstruction(MI, O);817}818}819820static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)821{822int32_t imm;823MCOperand *Op = MCInst_getOperand(MI, OpNo);824825if (MCOperand_isReg(Op)) {826unsigned Reg = MCOperand_getReg(Op);827828printRegName(MI->csh, O, Reg);829830if (MI->csh->detail) {831if (MI->csh->doing_mem) {832if (MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base == ARM_REG_INVALID)833MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = Reg;834else835MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = Reg;836} else {837#ifndef CAPSTONE_DIET838uint8_t access;839#endif840841MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;842MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;843#ifndef CAPSTONE_DIET844access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);845MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;846MI->ac_idx++;847#endif848MI->flat_insn->detail->arm.op_count++;849}850}851} else if (MCOperand_isImm(Op)) {852unsigned int opc = MCInst_getOpcode(MI);853854imm = (int32_t)MCOperand_getImm(Op);855856// relative branch only has relative offset, so we have to update it857// to reflect absolute address.858// Note: in ARM, PC is always 2 instructions ahead, so we have to859// add 8 in ARM mode, or 4 in Thumb mode860// printf(">> opcode: %u\n", MCInst_getOpcode(MI));861if (ARM_rel_branch(MI->csh, opc)) {862uint32_t address;863864// only do this for relative branch865if (MI->csh->mode & CS_MODE_THUMB) {866address = (uint32_t)MI->address + 4;867if (ARM_blx_to_arm_mode(MI->csh, opc)) {868// here need to align down to the nearest 4-byte address869#define _ALIGN_DOWN(v, align_width) ((v/align_width)*align_width)870address = _ALIGN_DOWN(address, 4);871#undef _ALIGN_DOWN872}873} else {874address = (uint32_t)MI->address + 8;875}876877imm += address;878printUInt32Bang(O, imm);879} else {880switch(MI->flat_insn->id) {881default:882if (MI->csh->imm_unsigned)883printUInt32Bang(O, imm);884else885printInt32Bang(O, imm);886break;887case ARM_INS_AND:888case ARM_INS_ORR:889case ARM_INS_EOR:890case ARM_INS_BIC:891case ARM_INS_MVN:892// do not print number in negative form893printUInt32Bang(O, imm);894break;895}896}897898if (MI->csh->detail) {899if (MI->csh->doing_mem)900MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = imm;901else {902MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;903MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;904MI->flat_insn->detail->arm.op_count++;905}906}907}908}909910static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O)911{912MCOperand *MO1 = MCInst_getOperand(MI, OpNum);913int32_t OffImm;914bool isSub;915SStream_concat0(O, "[pc, ");916917OffImm = (int32_t)MCOperand_getImm(MO1);918isSub = OffImm < 0;919920// Special value for #-0. All others are normal.921if (OffImm == INT32_MIN)922OffImm = 0;923924if (isSub) {925SStream_concat(O, "#-0x%x", -OffImm);926} else {927printUInt32Bang(O, OffImm);928}929930SStream_concat0(O, "]");931932if (MI->csh->detail) {933MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;934MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_PC;935MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;936MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;937MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;938MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;939MI->flat_insn->detail->arm.op_count++;940}941}942943// so_reg is a 4-operand unit corresponding to register forms of the A5.1944// "Addressing Mode 1 - Data-processing operands" forms. This includes:945// REG 0 0 - e.g. R5946// REG REG 0,SH_OPC - e.g. R5, ROR R3947// REG 0 IMM,SH_OPC - e.g. R5, LSL #3948static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O)949{950MCOperand *MO1 = MCInst_getOperand(MI, OpNum);951MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);952MCOperand *MO3 = MCInst_getOperand(MI, OpNum + 2);953ARM_AM_ShiftOpc ShOpc;954955printRegName(MI->csh, O, MCOperand_getReg(MO1));956957if (MI->csh->detail) {958MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;959MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);960MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;961962MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (MCOperand_getImm(MO3) & 7) + ARM_SFT_ASR_REG - 1;963MI->flat_insn->detail->arm.op_count++;964}965966// Print the shift opc.967ShOpc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));968SStream_concat0(O, ", ");969SStream_concat0(O, ARM_AM_getShiftOpcStr(ShOpc));970if (ShOpc == ARM_AM_rrx)971return;972973SStream_concat0(O, " ");974975printRegName(MI->csh, O, MCOperand_getReg(MO2));976977if (MI->csh->detail)978MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = MCOperand_getReg(MO2);979}980981static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O)982{983MCOperand *MO1 = MCInst_getOperand(MI, OpNum);984MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);985986printRegName(MI->csh, O, MCOperand_getReg(MO1));987988if (MI->csh->detail) {989MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;990MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);991MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;992MI->flat_insn->detail->arm.op_count++;993}994995// Print the shift opc.996printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),997getSORegOffset((unsigned int)MCOperand_getImm(MO2)));998}9991000//===--------------------------------------------------------------------===//1001// Addressing Mode #21002//===--------------------------------------------------------------------===//10031004static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)1005{1006MCOperand *MO1 = MCInst_getOperand(MI, Op);1007MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);1008MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);1009unsigned int imm3 = (unsigned int)MCOperand_getImm(MO3);1010ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));10111012SStream_concat0(O, "[");1013set_mem_access(MI, true);10141015printRegName(MI->csh, O, MCOperand_getReg(MO1));1016if (MI->csh->detail) {1017MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);1018}10191020if (!MCOperand_getReg(MO2)) {1021unsigned tmp = getAM2Offset(imm3);1022if (tmp) { // Don't print +0.1023subtracted = getAM2Op(imm3);10241025SStream_concat0(O, ", ");1026if (tmp > HEX_THRESHOLD)1027SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), tmp);1028else1029SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), tmp);1030if (MI->csh->detail) {1031MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)getAM2Op(imm3);1032MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = tmp;1033MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;1034}1035}10361037SStream_concat0(O, "]");1038set_mem_access(MI, false);10391040return;1041}10421043SStream_concat0(O, ", ");1044SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));1045printRegName(MI->csh, O, MCOperand_getReg(MO2));1046if (MI->csh->detail) {1047MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);1048MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;1049}10501051printRegImmShift(MI, O, getAM2ShiftOpc(imm3), getAM2Offset(imm3));1052SStream_concat0(O, "]");1053set_mem_access(MI, false);1054}10551056static void printAddrModeTBB(MCInst *MI, unsigned Op, SStream *O)1057{1058MCOperand *MO1 = MCInst_getOperand(MI, Op);1059MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);10601061SStream_concat0(O, "[");1062set_mem_access(MI, true);10631064printRegName(MI->csh, O, MCOperand_getReg(MO1));10651066if (MI->csh->detail)1067MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);10681069SStream_concat0(O, ", ");1070printRegName(MI->csh, O, MCOperand_getReg(MO2));10711072if (MI->csh->detail)1073MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);10741075SStream_concat0(O, "]");1076set_mem_access(MI, false);1077}10781079static void printAddrModeTBH(MCInst *MI, unsigned Op, SStream *O)1080{1081MCOperand *MO1 = MCInst_getOperand(MI, Op);1082MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);10831084SStream_concat0(O, "[");1085set_mem_access(MI, true);10861087printRegName(MI->csh, O, MCOperand_getReg(MO1));10881089if (MI->csh->detail)1090MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);10911092SStream_concat0(O, ", ");1093printRegName(MI->csh, O, MCOperand_getReg(MO2));10941095if (MI->csh->detail)1096MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);10971098SStream_concat0(O, ", lsl #1]");10991100if (MI->csh->detail) {1101MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;1102MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = 1;1103MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.lshift = 1;1104}11051106set_mem_access(MI, false);1107}11081109static void printAddrMode2Operand(MCInst *MI, unsigned Op, SStream *O)1110{1111MCOperand *MO1 = MCInst_getOperand(MI, Op);11121113if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.1114printOperand(MI, Op, O);1115return;1116}11171118//#ifndef NDEBUG1119// const MCOperand &MO3 = MI->getOperand(Op + 2);1120// unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());1121// assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");1122//#endif11231124printAM2PreOrOffsetIndexOp(MI, Op, O);1125}11261127static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)1128{1129MCOperand *MO1 = MCInst_getOperand(MI, OpNum);1130MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);1131ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));11321133if (!MCOperand_getReg(MO1)) {1134unsigned ImmOffs = getAM2Offset((unsigned int)MCOperand_getImm(MO2));1135if (ImmOffs > HEX_THRESHOLD)1136SStream_concat(O, "#%s0x%x",1137ARM_AM_getAddrOpcStr(subtracted), ImmOffs);1138else1139SStream_concat(O, "#%s%u",1140ARM_AM_getAddrOpcStr(subtracted), ImmOffs);11411142if (MI->csh->detail) {1143MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1144MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;1145MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;1146MI->flat_insn->detail->arm.op_count++;1147}1148return;1149}11501151SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));1152printRegName(MI->csh, O, MCOperand_getReg(MO1));11531154if (MI->csh->detail) {1155MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1156MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);1157MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;1158MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;1159MI->flat_insn->detail->arm.op_count++;1160}11611162printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO2)),1163getAM2Offset((unsigned int)MCOperand_getImm(MO2)));1164}11651166//===--------------------------------------------------------------------===//1167// Addressing Mode #31168//===--------------------------------------------------------------------===//11691170static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,1171bool AlwaysPrintImm0)1172{1173MCOperand *MO1 = MCInst_getOperand(MI, Op);1174MCOperand *MO2 = MCInst_getOperand(MI, Op+1);1175MCOperand *MO3 = MCInst_getOperand(MI, Op+2);1176ARM_AM_AddrOpc sign = getAM3Op((unsigned int)MCOperand_getImm(MO3));1177unsigned ImmOffs;11781179SStream_concat0(O, "[");1180set_mem_access(MI, true);11811182printRegName(MI->csh, O, MCOperand_getReg(MO1));11831184if (MI->csh->detail)1185MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);11861187if (MCOperand_getReg(MO2)) {1188SStream_concat0(O, ", ");1189SStream_concat0(O, ARM_AM_getAddrOpcStr(sign));11901191printRegName(MI->csh, O, MCOperand_getReg(MO2));11921193if (MI->csh->detail) {1194MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);1195if (sign == ARM_AM_sub) {1196MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = -1;1197MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;1198}1199}12001201SStream_concat0(O, "]");1202set_mem_access(MI, false);12031204return;1205}12061207// If the op is sub we have to print the immediate even if it is 01208ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));12091210if (AlwaysPrintImm0 || ImmOffs || (sign == ARM_AM_sub)) {1211if (ImmOffs > HEX_THRESHOLD)1212SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(sign), ImmOffs);1213else1214SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(sign), ImmOffs);1215}12161217if (MI->csh->detail) {1218if (sign == ARM_AM_sub) {1219MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs;1220MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;1221} else1222MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)ImmOffs;1223}12241225SStream_concat0(O, "]");1226set_mem_access(MI, false);1227}12281229static void printAddrMode3Operand(MCInst *MI, unsigned Op, SStream *O,1230bool AlwaysPrintImm0)1231{1232MCOperand *MO1 = MCInst_getOperand(MI, Op);12331234if (!MCOperand_isReg(MO1)) { // For label symbolic references.1235printOperand(MI, Op, O);1236return;1237}12381239printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);1240}12411242static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)1243{1244MCOperand *MO1 = MCInst_getOperand(MI, OpNum);1245MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);1246ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO2));1247unsigned ImmOffs;12481249if (MCOperand_getReg(MO1)) {1250SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));1251printRegName(MI->csh, O, MCOperand_getReg(MO1));12521253if (MI->csh->detail) {1254MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1255MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);1256MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;1257MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;1258MI->flat_insn->detail->arm.op_count++;1259}12601261return;1262}12631264ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO2));1265if (ImmOffs > HEX_THRESHOLD)1266SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);1267else1268SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);12691270if (MI->csh->detail) {1271MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1272MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;1273MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;1274MI->flat_insn->detail->arm.op_count++;1275}1276}12771278static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O)1279{1280MCOperand *MO = MCInst_getOperand(MI, OpNum);1281unsigned Imm = (unsigned int)MCOperand_getImm(MO);12821283if ((Imm & 0xff) > HEX_THRESHOLD)1284SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), (Imm & 0xff));1285else1286SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), (Imm & 0xff));12871288if (MI->csh->detail) {1289MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1290MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm & 0xff;1291MI->flat_insn->detail->arm.op_count++;1292}1293}12941295static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O)1296{1297MCOperand *MO1 = MCInst_getOperand(MI, OpNum);1298MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);12991300SStream_concat0(O, (MCOperand_getImm(MO2) ? "" : "-"));1301printRegName(MI->csh, O, MCOperand_getReg(MO1));13021303if (MI->csh->detail) {1304MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1305MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);1306MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;1307MI->flat_insn->detail->arm.op_count++;1308}1309}13101311static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O)1312{1313MCOperand *MO = MCInst_getOperand(MI, OpNum);1314int Imm = (int)MCOperand_getImm(MO);13151316if (((Imm & 0xff) << 2) > HEX_THRESHOLD) {1317SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));1318} else {1319SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));1320}13211322if (MI->csh->detail) {1323int v = (Imm & 256) ? ((Imm & 0xff) << 2) : -((Imm & 0xff) << 2);1324MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1325MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;1326MI->flat_insn->detail->arm.op_count++;1327}1328}13291330static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,1331bool AlwaysPrintImm0)1332{1333unsigned ImmOffs;1334MCOperand *MO1 = MCInst_getOperand(MI, OpNum);1335MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);1336ARM_AM_AddrOpc Op = ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2));13371338if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.1339printOperand(MI, OpNum, O);1340return;1341}13421343SStream_concat0(O, "[");1344printRegName(MI->csh, O, MCOperand_getReg(MO1));13451346if (MI->csh->detail) {1347MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;1348MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);1349MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;1350MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;1351MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;1352MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;1353}13541355ImmOffs = ARM_AM_getAM5Offset((unsigned int)MCOperand_getImm(MO2));1356if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {1357if (ImmOffs * 4 > HEX_THRESHOLD)1358SStream_concat(O, ", #%s0x%x",1359ARM_AM_getAddrOpcStr(Op),1360ImmOffs * 4);1361else1362SStream_concat(O, ", #%s%u",1363ARM_AM_getAddrOpcStr(Op),1364ImmOffs * 4);13651366if (MI->csh->detail) {1367if (Op)1368MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 4;1369else1370MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs * 4;1371}1372}13731374SStream_concat0(O, "]");13751376if (MI->csh->detail) {1377MI->flat_insn->detail->arm.op_count++;1378}1379}13801381static void printAddrMode5FP16Operand(MCInst *MI, unsigned OpNum, SStream *O,1382bool AlwaysPrintImm0)1383{1384MCOperand *MO1 = MCInst_getOperand(MI, OpNum);1385MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);1386unsigned ImmOffs = getAM5FP16Offset((unsigned)MCOperand_getImm(MO2));1387unsigned Op = getAM5FP16Op((unsigned)MCOperand_getImm(MO2));13881389if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.1390printOperand(MI, OpNum, O);1391return;1392}13931394SStream_concat0(O, "[");1395printRegName(MI->csh, O, MCOperand_getReg(MO1));13961397if (MI->csh->detail) {1398MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;1399MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);1400MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;1401MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;1402MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;1403MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;1404}14051406if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {1407if (ImmOffs * 2 > HEX_THRESHOLD)1408SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(Op), ImmOffs * 2);1409else1410SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(Op), ImmOffs * 2);14111412if (MI->csh->detail) {1413if (Op)1414MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 2;1415else1416MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs * 2;1417}1418}14191420SStream_concat0(O, "]");14211422if (MI->csh->detail) {1423MI->flat_insn->detail->arm.op_count++;1424}1425}14261427static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O)1428{1429MCOperand *MO1 = MCInst_getOperand(MI, OpNum);1430MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);1431unsigned tmp;14321433SStream_concat0(O, "[");1434set_mem_access(MI, true);14351436printRegName(MI->csh, O, MCOperand_getReg(MO1));14371438if (MI->csh->detail)1439MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);14401441tmp = (unsigned int)MCOperand_getImm(MO2);1442if (tmp) {1443if (tmp << 3 > HEX_THRESHOLD)1444SStream_concat(O, ":0x%x", (tmp << 3));1445else1446SStream_concat(O, ":%u", (tmp << 3));14471448if (MI->csh->detail)1449MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp << 3;1450}14511452SStream_concat0(O, "]");1453set_mem_access(MI, false);1454}14551456static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O)1457{1458MCOperand *MO1 = MCInst_getOperand(MI, OpNum);14591460SStream_concat0(O, "[");1461set_mem_access(MI, true);14621463printRegName(MI->csh, O, MCOperand_getReg(MO1));14641465if (MI->csh->detail)1466MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);14671468SStream_concat0(O, "]");1469set_mem_access(MI, false);1470}14711472static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)1473{1474MCOperand *MO = MCInst_getOperand(MI, OpNum);14751476if (MCOperand_getReg(MO) == 0) {1477MI->writeback = true;1478SStream_concat0(O, "!");1479} else {1480SStream_concat0(O, ", ");1481printRegName(MI->csh, O, MCOperand_getReg(MO));14821483if (MI->csh->detail) {1484MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1485MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO);1486MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;1487MI->flat_insn->detail->arm.op_count++;1488}1489}1490}14911492static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O)1493{1494MCOperand *MO = MCInst_getOperand(MI, OpNum);1495uint32_t v = ~(uint32_t)MCOperand_getImm(MO);1496int32_t lsb = CountTrailingZeros_32(v);1497int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;14981499//assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");1500printUInt32Bang(O, lsb);15011502if (width > HEX_THRESHOLD)1503SStream_concat(O, ", #0x%x", width);1504else1505SStream_concat(O, ", #%u", width);15061507if (MI->csh->detail) {1508MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1509MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = lsb;1510MI->flat_insn->detail->arm.op_count++;1511MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1512MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = width;1513MI->flat_insn->detail->arm.op_count++;1514}1515}15161517static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O)1518{1519unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1520SStream_concat0(O, ARM_MB_MemBOptToString(val,1521ARM_getFeatureBits(MI->csh->mode, ARM_HasV8Ops)));15221523if (MI->csh->detail) {1524MI->flat_insn->detail->arm.mem_barrier = (arm_mem_barrier)(val + 1);1525}1526}15271528static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)1529{1530unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1531SStream_concat0(O, ARM_ISB_InstSyncBOptToString(val));1532}15331534static void printTraceSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)1535{1536unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1537SStream_concat0(O, ARM_TSB_TraceSyncBOptToString(val));1538// TODO: add to detail?1539}15401541static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O)1542{1543unsigned ShiftOp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1544bool isASR = (ShiftOp & (1 << 5)) != 0;1545unsigned Amt = ShiftOp & 0x1f;15461547if (isASR) {1548unsigned tmp = Amt == 0 ? 32 : Amt;1549if (tmp > HEX_THRESHOLD)1550SStream_concat(O, ", asr #0x%x", tmp);1551else1552SStream_concat(O, ", asr #%u", tmp);15531554if (MI->csh->detail) {1555MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;1556MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;1557}1558} else if (Amt) {1559if (Amt > HEX_THRESHOLD)1560SStream_concat(O, ", lsl #0x%x", Amt);1561else1562SStream_concat(O, ", lsl #%u", Amt);15631564if (MI->csh->detail) {1565MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;1566MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Amt;1567}1568}1569}15701571static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O)1572{1573unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));15741575if (Imm == 0)1576return;15771578//assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");1579if (Imm > HEX_THRESHOLD)1580SStream_concat(O, ", lsl #0x%x", Imm);1581else1582SStream_concat(O, ", lsl #%u", Imm);15831584if (MI->csh->detail) {1585MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;1586MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;1587}1588}15891590static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O)1591{1592unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));15931594// A shift amount of 32 is encoded as 0.1595if (Imm == 0)1596Imm = 32;15971598//assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");1599if (Imm > HEX_THRESHOLD)1600SStream_concat(O, ", asr #0x%x", Imm);1601else1602SStream_concat(O, ", asr #%u", Imm);16031604if (MI->csh->detail) {1605MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;1606MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;1607}1608}16091610// FIXME: push {r1, r2, r3, ...} can exceed the number of operands in MCInst struct1611static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O)1612{1613unsigned i, e;1614#ifndef CAPSTONE_DIET1615uint8_t access = 0;1616#endif16171618SStream_concat0(O, "{");16191620#ifndef CAPSTONE_DIET1621if (MI->csh->detail) {1622access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);1623}1624#endif16251626for (i = OpNum, e = MCInst_getNumOperands(MI); i != e; ++i) {1627if (i != OpNum)1628SStream_concat0(O, ", ");16291630printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, i)));16311632if (MI->csh->detail) {1633MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1634MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, i));1635#ifndef CAPSTONE_DIET1636MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;1637#endif1638MI->flat_insn->detail->arm.op_count++;1639}1640}16411642SStream_concat0(O, "}");16431644#ifndef CAPSTONE_DIET1645if (MI->csh->detail) {1646MI->ac_idx++;1647}1648#endif1649}16501651static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O)1652{1653unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));16541655printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_0));16561657if (MI->csh->detail) {1658MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1659MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_0);1660MI->flat_insn->detail->arm.op_count++;1661}16621663SStream_concat0(O, ", ");16641665printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_1));16661667if (MI->csh->detail) {1668MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;1669MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_1);1670MI->flat_insn->detail->arm.op_count++;1671}1672}16731674// SETEND BE/LE1675static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O)1676{1677MCOperand *Op = MCInst_getOperand(MI, OpNum);16781679if (MCOperand_getImm(Op)) {1680SStream_concat0(O, "be");16811682if (MI->csh->detail) {1683MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;1684MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_BE;1685MI->flat_insn->detail->arm.op_count++;1686}1687} else {1688SStream_concat0(O, "le");16891690if (MI->csh->detail) {1691MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;1692MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_LE;1693MI->flat_insn->detail->arm.op_count++;1694}1695}1696}16971698static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O)1699{1700MCOperand *Op = MCInst_getOperand(MI, OpNum);1701unsigned int mode = (unsigned int)MCOperand_getImm(Op);17021703SStream_concat0(O, ARM_PROC_IModToString(mode));17041705if (MI->csh->detail) {1706MI->flat_insn->detail->arm.cps_mode = mode;1707}1708}17091710static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O)1711{1712MCOperand *Op = MCInst_getOperand(MI, OpNum);1713unsigned IFlags = (unsigned int)MCOperand_getImm(Op);1714int i;17151716for (i = 2; i >= 0; --i)1717if (IFlags & (1 << i)) {1718SStream_concat0(O, ARM_PROC_IFlagsToString(1 << i));1719}17201721if (IFlags == 0) {1722SStream_concat0(O, "none");1723IFlags = ARM_CPSFLAG_NONE;1724}17251726if (MI->csh->detail) {1727MI->flat_insn->detail->arm.cps_flag = IFlags;1728}1729}17301731static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O)1732{1733MCOperand *Op = MCInst_getOperand(MI, OpNum);1734unsigned SpecRegRBit = (unsigned)MCOperand_getImm(Op) >> 4;1735unsigned Mask = (unsigned)MCOperand_getImm(Op) & 0xf;1736unsigned reg;17371738if (ARM_getFeatureBits(MI->csh->mode, ARM_FeatureMClass)) {1739const MClassSysReg *TheReg;1740unsigned SYSm = (unsigned)MCOperand_getImm(Op) & 0xFFF; // 12-bit SYMm1741unsigned Opcode = MCInst_getOpcode(MI);17421743if (Opcode == ARM_t2MSR_M && ARM_getFeatureBits(MI->csh->mode, ARM_FeatureDSP)) {1744TheReg = lookupMClassSysRegBy12bitSYSmValue(SYSm);1745if (TheReg && MClassSysReg_isInRequiredFeatures(TheReg, ARM_FeatureDSP)) {1746SStream_concat0(O, TheReg->Name);1747ARM_addSysReg(MI, TheReg->sysreg);1748return;1749}1750}17511752// Handle the basic 8-bit mask.1753SYSm &= 0xff;1754if (Opcode == ARM_t2MSR_M && ARM_getFeatureBits(MI->csh->mode, ARM_HasV7Ops)) {1755// ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an1756// alias for MSR APSR_nzcvq.1757TheReg = lookupMClassSysRegAPSRNonDeprecated(SYSm);1758if (TheReg) {1759SStream_concat0(O, TheReg->Name);1760ARM_addSysReg(MI, TheReg->sysreg);1761return;1762}1763}17641765TheReg = lookupMClassSysRegBy8bitSYSmValue(SYSm);1766if (TheReg) {1767SStream_concat0(O, TheReg->Name);1768ARM_addSysReg(MI, TheReg->sysreg);1769return;1770}17711772if (SYSm > HEX_THRESHOLD)1773SStream_concat(O, "%x", SYSm);1774else1775SStream_concat(O, "%u", SYSm);17761777if (MI->csh->detail)1778MCOperand_CreateImm0(MI, SYSm);17791780return;1781}17821783// As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as1784// APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.1785if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {1786SStream_concat0(O, "apsr_");1787switch (Mask) {1788default: // llvm_unreachable("Unexpected mask value!");1789case 4: SStream_concat0(O, "g"); ARM_addSysReg(MI, ARM_SYSREG_APSR_G); return;1790case 8: SStream_concat0(O, "nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQ); return;1791case 12: SStream_concat0(O, "nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQG); return;1792}1793}17941795if (SpecRegRBit) {1796SStream_concat0(O, "spsr");1797} else {1798SStream_concat0(O, "cpsr");1799}18001801reg = 0;1802if (Mask) {1803SStream_concat0(O, "_");18041805if (Mask & 8) {1806SStream_concat0(O, "f");1807reg += SpecRegRBit ? ARM_SYSREG_SPSR_F : ARM_SYSREG_CPSR_F;1808}18091810if (Mask & 4) {1811SStream_concat0(O, "s");1812reg += SpecRegRBit ? ARM_SYSREG_SPSR_S : ARM_SYSREG_CPSR_S;1813}18141815if (Mask & 2) {1816SStream_concat0(O, "x");1817reg += SpecRegRBit ? ARM_SYSREG_SPSR_X : ARM_SYSREG_CPSR_X;1818}18191820if (Mask & 1) {1821SStream_concat0(O, "c");1822reg += SpecRegRBit ? ARM_SYSREG_SPSR_C : ARM_SYSREG_CPSR_C;1823}18241825ARM_addSysReg(MI, reg);1826}1827}18281829static void printBankedRegOperand(MCInst *MI, unsigned OpNum, SStream *O)1830{1831uint32_t Banked = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1832const BankedReg *TheReg = lookupBankedRegByEncoding(Banked);18331834SStream_concat0(O, TheReg->Name);1835ARM_addSysReg(MI, TheReg->sysreg);1836}18371838static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)1839{1840ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1841// Handle the undefined 15 CC value here for printing so we don't abort().1842if ((unsigned)CC == 15) {1843SStream_concat0(O, "<und>");18441845if (MI->csh->detail)1846MI->flat_insn->detail->arm.cc = ARM_CC_INVALID;1847} else {1848if (CC != ARMCC_AL) {1849SStream_concat0(O, ARMCC_ARMCondCodeToString(CC));1850}18511852if (MI->csh->detail)1853MI->flat_insn->detail->arm.cc = CC + 1;1854}1855}18561857static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)1858{1859ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1860SStream_concat0(O, ARMCC_ARMCondCodeToString(CC));18611862if (MI->csh->detail)1863MI->flat_insn->detail->arm.cc = CC + 1;1864}18651866static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O)1867{1868if (MCOperand_getReg(MCInst_getOperand(MI, OpNum))) {1869//assert(MCOperand_getReg(MCInst_getOperand(MI, OpNum)) == ARM_CPSR &&1870// "Expect ARM CPSR register!");1871SStream_concat0(O, "s");18721873if (MI->csh->detail)1874MI->flat_insn->detail->arm.update_flags = true;1875}1876}18771878static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O)1879{1880unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));18811882printUInt32(O, tmp);18831884if (MI->csh->detail) {1885if (MI->csh->doing_mem) {1886MI->flat_insn->detail->arm.op_count--;1887MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].neon_lane = (int8_t)tmp;1888MI->ac_idx--; // consecutive operands share the same access right1889} else {1890MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1891MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;1892MI->flat_insn->detail->arm.op_count++;1893}1894}1895}18961897static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O)1898{1899unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));19001901SStream_concat(O, "p%u", imm);19021903if (MI->csh->detail) {1904MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_PIMM;1905MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;1906MI->flat_insn->detail->arm.op_count++;1907}1908}19091910static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O)1911{1912unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));19131914SStream_concat(O, "c%u", imm);19151916if (MI->csh->detail) {1917MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_CIMM;1918MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;1919MI->flat_insn->detail->arm.op_count++;1920}1921}19221923static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O)1924{1925unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1926if (tmp > HEX_THRESHOLD)1927SStream_concat(O, "{0x%x}", tmp);1928else1929SStream_concat(O, "{%u}", tmp);19301931if (MI->csh->detail) {1932MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1933MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;1934MI->flat_insn->detail->arm.op_count++;1935}1936}19371938static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned scale)1939{1940MCOperand *MO = MCInst_getOperand(MI, OpNum);19411942int32_t OffImm = (int32_t)MCOperand_getImm(MO) << scale;19431944if (OffImm == INT32_MIN) {1945SStream_concat0(O, "#-0");19461947if (MI->csh->detail) {1948MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1949MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;1950MI->flat_insn->detail->arm.op_count++;1951}1952} else {1953if (OffImm < 0)1954SStream_concat(O, "#-0x%x", -OffImm);1955else {1956if (OffImm > HEX_THRESHOLD)1957SStream_concat(O, "#0x%x", OffImm);1958else1959SStream_concat(O, "#%u", OffImm);1960}19611962if (MI->csh->detail) {1963MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1964MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;1965MI->flat_insn->detail->arm.op_count++;1966}1967}1968}19691970static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O)1971{1972unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4;19731974printUInt32Bang(O, tmp);19751976if (MI->csh->detail) {1977MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1978MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;1979MI->flat_insn->detail->arm.op_count++;1980}1981}19821983static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O)1984{1985unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));1986unsigned tmp = Imm == 0 ? 32 : Imm;19871988printUInt32Bang(O, tmp);19891990if (MI->csh->detail) {1991MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;1992MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;1993MI->flat_insn->detail->arm.op_count++;1994}1995}19961997static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O)1998{1999// (3 - the number of trailing zeros) is the number of then / else.2000unsigned Mask = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));2001unsigned Firstcond = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum - 1));2002unsigned CondBit0 = Firstcond & 1;2003unsigned NumTZ = CountTrailingZeros_32(Mask);2004//assert(NumTZ <= 3 && "Invalid IT mask!");2005unsigned Pos, e;20062007for (Pos = 3, e = NumTZ; Pos > e; --Pos) {2008bool T = ((Mask >> Pos) & 1) == CondBit0;2009if (T)2010SStream_concat0(O, "t");2011else2012SStream_concat0(O, "e");2013// TODO: detail for this t/e2014}2015}20162017static void printThumbAddrModeRROperand(MCInst *MI, unsigned Op, SStream *O)2018{2019MCOperand *MO1 = MCInst_getOperand(MI, Op);2020MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);2021unsigned RegNum;20222023if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.2024printOperand(MI, Op, O);2025return;2026}20272028SStream_concat0(O, "[");2029set_mem_access(MI, true);20302031printRegName(MI->csh, O, MCOperand_getReg(MO1));20322033if (MI->csh->detail)2034MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);20352036RegNum = MCOperand_getReg(MO2);2037if (RegNum) {2038SStream_concat0(O, ", ");2039printRegName(MI->csh, O, RegNum);20402041if (MI->csh->detail)2042MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = RegNum;2043}20442045SStream_concat0(O, "]");2046set_mem_access(MI, false);2047}20482049static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned Op, SStream *O,2050unsigned Scale)2051{2052MCOperand *MO1 = MCInst_getOperand(MI, Op);2053MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);2054unsigned ImmOffs, tmp;20552056if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.2057printOperand(MI, Op, O);2058return;2059}20602061SStream_concat0(O, "[");2062set_mem_access(MI, true);20632064printRegName(MI->csh, O, MCOperand_getReg(MO1));20652066if (MI->csh->detail)2067MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);20682069ImmOffs = (unsigned int)MCOperand_getImm(MO2);2070if (ImmOffs) {2071tmp = ImmOffs * Scale;2072SStream_concat0(O, ", ");2073printUInt32Bang(O, tmp);20742075if (MI->csh->detail)2076MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;2077}20782079SStream_concat0(O, "]");2080set_mem_access(MI, false);2081}20822083static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned Op, SStream *O)2084{2085printThumbAddrModeImm5SOperand(MI, Op, O, 1);2086}20872088static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned Op, SStream *O)2089{2090printThumbAddrModeImm5SOperand(MI, Op, O, 2);2091}20922093static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned Op, SStream *O)2094{2095printThumbAddrModeImm5SOperand(MI, Op, O, 4);2096}20972098static void printThumbAddrModeSPOperand(MCInst *MI, unsigned Op, SStream *O)2099{2100printThumbAddrModeImm5SOperand(MI, Op, O, 4);2101}21022103// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb22104// register with shift forms.2105// REG 0 0 - e.g. R52106// REG IMM, SH_OPC - e.g. R5, LSL #32107static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O)2108{2109MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2110MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);2111unsigned Reg = MCOperand_getReg(MO1);21122113printRegName(MI->csh, O, Reg);21142115if (MI->csh->detail) {2116MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2117MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;2118MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;2119MI->flat_insn->detail->arm.op_count++;2120}21212122// Print the shift opc.2123//assert(MO2.isImm() && "Not a valid t2_so_reg value!");2124printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),2125getSORegOffset((unsigned int)MCOperand_getImm(MO2)));2126}21272128static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum,2129SStream *O, bool AlwaysPrintImm0)2130{2131MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2132MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);2133int32_t OffImm;2134bool isSub;21352136if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.2137printOperand(MI, OpNum, O);2138return;2139}21402141SStream_concat0(O, "[");2142set_mem_access(MI, true);21432144printRegName(MI->csh, O, MCOperand_getReg(MO1));21452146if (MI->csh->detail)2147MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);21482149OffImm = (int32_t)MCOperand_getImm(MO2);2150isSub = OffImm < 0;21512152// Special value for #-0. All others are normal.2153if (OffImm == INT32_MIN)2154OffImm = 0;21552156if (isSub) {2157if (OffImm < -HEX_THRESHOLD)2158SStream_concat(O, ", #-0x%x", -OffImm);2159else2160SStream_concat(O, ", #-%u", -OffImm);2161} else if (AlwaysPrintImm0 || OffImm > 0) {2162if (OffImm >= 0) {2163if (OffImm > HEX_THRESHOLD)2164SStream_concat(O, ", #0x%x", OffImm);2165else2166SStream_concat(O, ", #%u", OffImm);2167} else {2168if (OffImm < -HEX_THRESHOLD)2169SStream_concat(O, ", #-0x%x", -OffImm);2170else2171SStream_concat(O, ", #-%u", -OffImm);2172}2173}21742175if (MI->csh->detail)2176MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;21772178SStream_concat0(O, "]");2179set_mem_access(MI, false);2180}21812182static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O,2183bool AlwaysPrintImm0)2184{2185MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2186MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);2187int32_t OffImm;2188bool isSub;21892190SStream_concat0(O, "[");2191set_mem_access(MI, true);21922193printRegName(MI->csh, O, MCOperand_getReg(MO1));21942195if (MI->csh->detail)2196MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);21972198OffImm = (int32_t)MCOperand_getImm(MO2);2199isSub = OffImm < 0;22002201// Don't print +0.2202if (OffImm == INT32_MIN)2203OffImm = 0;22042205if (isSub)2206SStream_concat(O, ", #-0x%x", -OffImm);2207else if (AlwaysPrintImm0 || OffImm > 0) {2208if (OffImm > HEX_THRESHOLD)2209SStream_concat(O, ", #0x%x", OffImm);2210else2211SStream_concat(O, ", #%u", OffImm);2212}22132214if (MI->csh->detail)2215MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;22162217SStream_concat0(O, "]");2218set_mem_access(MI, false);2219}22202221static void printT2AddrModeImm8s4Operand(MCInst *MI,2222unsigned OpNum, SStream *O, bool AlwaysPrintImm0)2223{2224MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2225MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);2226int32_t OffImm;2227bool isSub;22282229if (!MCOperand_isReg(MO1)) { // For label symbolic references.2230printOperand(MI, OpNum, O);2231return;2232}22332234SStream_concat0(O, "[");2235set_mem_access(MI, true);22362237printRegName(MI->csh, O, MCOperand_getReg(MO1));22382239if (MI->csh->detail)2240MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);22412242OffImm = (int32_t)MCOperand_getImm(MO2);2243isSub = OffImm < 0;22442245//assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");22462247// Don't print +0.2248if (OffImm == INT32_MIN)2249OffImm = 0;22502251if (isSub) {2252SStream_concat(O, ", #-0x%x", -OffImm);2253} else if (AlwaysPrintImm0 || OffImm > 0) {2254if (OffImm > HEX_THRESHOLD)2255SStream_concat(O, ", #0x%x", OffImm);2256else2257SStream_concat(O, ", #%u", OffImm);2258}22592260if (MI->csh->detail)2261MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;22622263SStream_concat0(O, "]");2264set_mem_access(MI, false);2265}22662267static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O)2268{2269MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2270MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);2271unsigned tmp;22722273SStream_concat0(O, "[");2274set_mem_access(MI, true);22752276printRegName(MI->csh, O, MCOperand_getReg(MO1));22772278if (MI->csh->detail)2279MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);22802281if (MCOperand_getImm(MO2)) {2282SStream_concat0(O, ", ");2283tmp = (unsigned int)MCOperand_getImm(MO2) * 4;2284printUInt32Bang(O, tmp);22852286if (MI->csh->detail)2287MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;2288}22892290SStream_concat0(O, "]");2291set_mem_access(MI, false);2292}22932294static void printT2AddrModeImm8OffsetOperand(MCInst *MI,2295unsigned OpNum, SStream *O)2296{2297MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2298int32_t OffImm = (int32_t)MCOperand_getImm(MO1);22992300SStream_concat0(O, ", ");2301if (OffImm == INT32_MIN) {2302SStream_concat0(O, "#-0");23032304if (MI->csh->detail) {2305MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2306MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;2307MI->flat_insn->detail->arm.op_count++;2308}2309} else {2310printInt32Bang(O, OffImm);23112312if (MI->csh->detail) {2313MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2314MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;2315MI->flat_insn->detail->arm.op_count++;2316}2317}2318}23192320static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI,2321unsigned OpNum, SStream *O)2322{2323MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2324int32_t OffImm = (int32_t)MCOperand_getImm(MO1);23252326//assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");23272328SStream_concat0(O, ", ");23292330if (OffImm == INT32_MIN) {2331SStream_concat0(O, "#-0");23322333if (MI->csh->detail) {2334MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2335MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;2336MI->flat_insn->detail->arm.op_count++;2337}2338} else {2339printInt32Bang(O, OffImm);23402341if (MI->csh->detail) {2342MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2343MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;2344MI->flat_insn->detail->arm.op_count++;2345}2346}2347}23482349static void printT2AddrModeSoRegOperand(MCInst *MI,2350unsigned OpNum, SStream *O)2351{2352MCOperand *MO1 = MCInst_getOperand(MI, OpNum);2353MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);2354MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);2355unsigned ShAmt;23562357SStream_concat0(O, "[");2358set_mem_access(MI, true);23592360printRegName(MI->csh, O, MCOperand_getReg(MO1));23612362if (MI->csh->detail)2363MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);23642365//assert(MCOperand_getReg(MO2.getReg() && "Invalid so_reg load / store address!");2366SStream_concat0(O, ", ");2367printRegName(MI->csh, O, MCOperand_getReg(MO2));23682369if (MI->csh->detail)2370MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);23712372ShAmt = (unsigned int)MCOperand_getImm(MO3);2373if (ShAmt) {2374//assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");2375SStream_concat0(O, ", lsl ");2376SStream_concat(O, "#%u", ShAmt);23772378if (MI->csh->detail) {2379MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;2380MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = ShAmt;2381}2382}23832384SStream_concat0(O, "]");2385set_mem_access(MI, false);2386}23872388static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)2389{2390MCOperand *MO = MCInst_getOperand(MI, OpNum);23912392#if defined(_KERNEL_MODE)2393// Issue #681: Windows kernel does not support formatting float point2394SStream_concat(O, "#<float_point_unsupported>");2395#else2396SStream_concat(O, "#%e", getFPImmFloat((unsigned int)MCOperand_getImm(MO)));2397#endif23982399if (MI->csh->detail) {2400MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_FP;2401MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].fp = getFPImmFloat((unsigned int)MCOperand_getImm(MO));2402MI->flat_insn->detail->arm.op_count++;2403}2404}24052406static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)2407{2408unsigned EncodedImm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));2409unsigned EltBits;2410uint64_t Val = ARM_AM_decodeNEONModImm(EncodedImm, &EltBits);24112412if (Val > HEX_THRESHOLD)2413SStream_concat(O, "#0x%"PRIx64, Val);2414else2415SStream_concat(O, "#%"PRIu64, Val);24162417if (MI->csh->detail) {2418MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2419MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = (unsigned int)Val;2420MI->flat_insn->detail->arm.op_count++;2421}2422}24232424static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O)2425{2426unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));24272428printUInt32Bang(O, Imm + 1);24292430if (MI->csh->detail) {2431MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2432MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm + 1;2433MI->flat_insn->detail->arm.op_count++;2434}2435}24362437static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O)2438{2439unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));24402441if (Imm == 0)2442return;24432444SStream_concat0(O, ", ror #");24452446switch (Imm) {2447default: //assert (0 && "illegal ror immediate!");2448case 1: SStream_concat0(O, "8"); break;2449case 2: SStream_concat0(O, "16"); break;2450case 3: SStream_concat0(O, "24"); break;2451}24522453if (MI->csh->detail) {2454MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ROR;2455MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm * 8;2456}2457}24582459static void printModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)2460{2461MCOperand *Op = MCInst_getOperand(MI, OpNum);2462unsigned Bits = MCOperand_getImm(Op) & 0xFF;2463unsigned Rot = (MCOperand_getImm(Op) & 0xF00) >> 7;2464int32_t Rotated;2465bool PrintUnsigned = false;24662467switch (MCInst_getOpcode(MI)) {2468case ARM_MOVi:2469// Movs to PC should be treated unsigned2470PrintUnsigned = (MCOperand_getReg(MCInst_getOperand(MI, OpNum - 1)) == ARM_PC);2471break;2472case ARM_MSRi:2473// Movs to special registers should be treated unsigned2474PrintUnsigned = true;2475break;2476}24772478Rotated = rotr32(Bits, Rot);2479if (getSOImmVal(Rotated) == MCOperand_getImm(Op)) {2480// #rot has the least possible value2481if (PrintUnsigned) {2482if (Rotated > HEX_THRESHOLD || Rotated < -HEX_THRESHOLD)2483SStream_concat(O, "#0x%x", Rotated);2484else2485SStream_concat(O, "#%u", Rotated);2486} else if (Rotated >= 0) {2487if (Rotated > HEX_THRESHOLD)2488SStream_concat(O, "#0x%x", Rotated);2489else2490SStream_concat(O, "#%u", Rotated);2491} else {2492SStream_concat(O, "#0x%x", Rotated);2493}24942495if (MI->csh->detail) {2496MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2497MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Rotated;2498MI->flat_insn->detail->arm.op_count++;2499}25002501return;2502}25032504// Explicit #bits, #rot implied2505SStream_concat(O, "#%u, #%u", Bits, Rot);25062507if (MI->csh->detail) {2508MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2509MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Bits;2510MI->flat_insn->detail->arm.op_count++;2511MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2512MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Rot;2513MI->flat_insn->detail->arm.op_count++;2514}2515}25162517static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O)2518{2519unsigned tmp;25202521tmp = 16 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));25222523printUInt32Bang(O, tmp);25242525if (MI->csh->detail) {2526MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2527MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;2528MI->flat_insn->detail->arm.op_count++;2529}2530}25312532static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O)2533{2534unsigned tmp;25352536tmp = 32 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));25372538printUInt32Bang(O, tmp);25392540if (MI->csh->detail) {2541MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;2542MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;2543MI->flat_insn->detail->arm.op_count++;2544}2545}25462547static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)2548{2549unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));25502551if (tmp > HEX_THRESHOLD)2552SStream_concat(O, "[0x%x]", tmp);2553else2554SStream_concat(O, "[%u]", tmp);25552556if (MI->csh->detail) {2557MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].vector_index = tmp;2558}2559}25602561static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O)2562{2563SStream_concat0(O, "{");25642565printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));25662567if (MI->csh->detail) {2568#ifndef CAPSTONE_DIET2569uint8_t access;25702571access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2572#endif25732574MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2575MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2576#ifndef CAPSTONE_DIET2577MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2578#endif2579MI->flat_insn->detail->arm.op_count++;25802581#ifndef CAPSTONE_DIET2582MI->ac_idx++;2583#endif2584}25852586SStream_concat0(O, "}");2587}25882589static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O)2590{2591#ifndef CAPSTONE_DIET2592uint8_t access;2593#endif2594unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2595unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);2596unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_1);25972598#ifndef CAPSTONE_DIET2599access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2600#endif26012602SStream_concat0(O, "{");26032604printRegName(MI->csh, O, Reg0);26052606if (MI->csh->detail) {2607MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2608MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;2609#ifndef CAPSTONE_DIET2610MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2611#endif2612MI->flat_insn->detail->arm.op_count++;2613}26142615SStream_concat0(O, ", ");26162617printRegName(MI->csh, O, Reg1);26182619if (MI->csh->detail) {2620MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2621MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;2622#ifndef CAPSTONE_DIET2623MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2624#endif2625MI->flat_insn->detail->arm.op_count++;2626}26272628SStream_concat0(O, "}");26292630#ifndef CAPSTONE_DIET2631MI->ac_idx++;2632#endif2633}26342635static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O)2636{2637#ifndef CAPSTONE_DIET2638uint8_t access;2639#endif2640unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2641unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);2642unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_2);26432644#ifndef CAPSTONE_DIET2645access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2646#endif26472648SStream_concat0(O, "{");26492650printRegName(MI->csh, O, Reg0);26512652if (MI->csh->detail) {2653MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2654MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;2655#ifndef CAPSTONE_DIET2656MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2657#endif2658MI->flat_insn->detail->arm.op_count++;2659}26602661SStream_concat0(O, ", ");26622663printRegName(MI->csh, O, Reg1);26642665if (MI->csh->detail) {2666MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2667MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;2668#ifndef CAPSTONE_DIET2669MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2670#endif2671MI->flat_insn->detail->arm.op_count++;2672}26732674SStream_concat0(O, "}");26752676#ifndef CAPSTONE_DIET2677MI->ac_idx++;2678#endif2679}26802681static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O)2682{2683#ifndef CAPSTONE_DIET2684uint8_t access;26852686access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2687#endif26882689// Normally, it's not safe to use register enum values directly with2690// addition to get the next register, but for VFP registers, the2691// sort order is guaranteed because they're all of the form D<n>.2692SStream_concat0(O, "{");26932694printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));26952696if (MI->csh->detail) {2697MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2698MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2699#ifndef CAPSTONE_DIET2700MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2701#endif2702MI->flat_insn->detail->arm.op_count++;2703}27042705SStream_concat0(O, ", ");27062707printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);27082709if (MI->csh->detail) {2710MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2711MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;2712#ifndef CAPSTONE_DIET2713MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2714#endif2715MI->flat_insn->detail->arm.op_count++;2716}27172718SStream_concat0(O, ", ");27192720printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);27212722if (MI->csh->detail) {2723MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2724MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;2725#ifndef CAPSTONE_DIET2726MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2727#endif2728MI->flat_insn->detail->arm.op_count++;2729}27302731SStream_concat0(O, "}");27322733#ifndef CAPSTONE_DIET2734MI->ac_idx++;2735#endif2736}27372738static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O)2739{2740#ifndef CAPSTONE_DIET2741uint8_t access;27422743access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2744#endif27452746// Normally, it's not safe to use register enum values directly with2747// addition to get the next register, but for VFP registers, the2748// sort order is guaranteed because they're all of the form D<n>.2749SStream_concat0(O, "{");27502751printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));27522753if (MI->csh->detail) {2754MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2755MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2756#ifndef CAPSTONE_DIET2757MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2758#endif2759MI->flat_insn->detail->arm.op_count++;2760}27612762SStream_concat0(O, ", ");27632764printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);27652766if (MI->csh->detail) {2767MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2768MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;2769#ifndef CAPSTONE_DIET2770MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2771#endif2772MI->flat_insn->detail->arm.op_count++;2773}27742775SStream_concat0(O, ", ");27762777printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);27782779if (MI->csh->detail) {2780MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2781MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;2782#ifndef CAPSTONE_DIET2783MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2784#endif2785MI->flat_insn->detail->arm.op_count++;2786}27872788SStream_concat0(O, ", ");27892790printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);27912792if (MI->csh->detail) {2793MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2794MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;2795#ifndef CAPSTONE_DIET2796MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2797#endif2798MI->flat_insn->detail->arm.op_count++;2799}28002801SStream_concat0(O, "}");28022803#ifndef CAPSTONE_DIET2804MI->ac_idx++;2805#endif2806}28072808static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O)2809{2810#ifndef CAPSTONE_DIET2811uint8_t access;28122813access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2814#endif28152816SStream_concat0(O, "{");28172818printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));28192820if (MI->csh->detail) {2821MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2822MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2823#ifndef CAPSTONE_DIET2824MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2825#endif2826MI->flat_insn->detail->arm.op_count++;2827}28282829SStream_concat0(O, "[]}");28302831#ifndef CAPSTONE_DIET2832MI->ac_idx++;2833#endif2834}28352836static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O)2837{2838#ifndef CAPSTONE_DIET2839uint8_t access;2840#endif2841unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2842unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);2843unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_1);28442845#ifndef CAPSTONE_DIET2846access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2847#endif28482849SStream_concat0(O, "{");28502851printRegName(MI->csh, O, Reg0);28522853if (MI->csh->detail) {2854MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2855MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;2856#ifndef CAPSTONE_DIET2857MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2858#endif2859MI->flat_insn->detail->arm.op_count++;2860}28612862SStream_concat0(O, "[], ");28632864printRegName(MI->csh, O, Reg1);28652866if (MI->csh->detail) {2867MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2868MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;2869#ifndef CAPSTONE_DIET2870MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2871#endif2872MI->flat_insn->detail->arm.op_count++;2873}28742875SStream_concat0(O, "[]}");28762877#ifndef CAPSTONE_DIET2878MI->ac_idx++;2879#endif2880}28812882static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O)2883{2884#ifndef CAPSTONE_DIET2885uint8_t access;28862887access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2888#endif28892890// Normally, it's not safe to use register enum values directly with2891// addition to get the next register, but for VFP registers, the2892// sort order is guaranteed because they're all of the form D<n>.2893SStream_concat0(O, "{");28942895printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));28962897if (MI->csh->detail) {2898MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2899MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2900#ifndef CAPSTONE_DIET2901MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2902#endif2903MI->flat_insn->detail->arm.op_count++;2904}29052906SStream_concat0(O, "[], ");29072908printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);29092910if (MI->csh->detail) {2911MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2912MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;2913#ifndef CAPSTONE_DIET2914MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2915#endif2916MI->flat_insn->detail->arm.op_count++;2917}29182919SStream_concat0(O, "[], ");29202921printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);29222923if (MI->csh->detail) {2924MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2925MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;2926#ifndef CAPSTONE_DIET2927MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2928#endif2929MI->flat_insn->detail->arm.op_count++;2930}29312932SStream_concat0(O, "[]}");29332934#ifndef CAPSTONE_DIET2935MI->ac_idx++;2936#endif2937}29382939static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O)2940{2941#ifndef CAPSTONE_DIET2942uint8_t access;29432944access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);2945#endif29462947// Normally, it's not safe to use register enum values directly with2948// addition to get the next register, but for VFP registers, the2949// sort order is guaranteed because they're all of the form D<n>.2950SStream_concat0(O, "{");29512952printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));29532954if (MI->csh->detail) {2955MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2956MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));2957#ifndef CAPSTONE_DIET2958MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2959#endif2960MI->flat_insn->detail->arm.op_count++;2961}29622963SStream_concat0(O, "[], ");29642965printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);29662967if (MI->csh->detail) {2968MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2969MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;2970#ifndef CAPSTONE_DIET2971MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2972#endif2973MI->flat_insn->detail->arm.op_count++;2974}29752976SStream_concat0(O, "[], ");29772978printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);29792980if (MI->csh->detail) {2981MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2982MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;2983#ifndef CAPSTONE_DIET2984MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2985#endif2986MI->flat_insn->detail->arm.op_count++;2987}29882989SStream_concat0(O, "[], ");29902991printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);29922993if (MI->csh->detail) {2994MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;2995MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;2996#ifndef CAPSTONE_DIET2997MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;2998#endif2999MI->flat_insn->detail->arm.op_count++;3000}30013002SStream_concat0(O, "[]}");30033004#ifndef CAPSTONE_DIET3005MI->ac_idx++;3006#endif3007}30083009static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O)3010{3011#ifndef CAPSTONE_DIET3012uint8_t access;3013#endif3014unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));3015unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);3016unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_2);30173018#ifndef CAPSTONE_DIET3019access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);3020#endif30213022SStream_concat0(O, "{");30233024printRegName(MI->csh, O, Reg0);30253026if (MI->csh->detail) {3027MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3028MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;3029#ifndef CAPSTONE_DIET3030MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3031#endif3032MI->flat_insn->detail->arm.op_count++;3033}30343035SStream_concat0(O, "[], ");30363037printRegName(MI->csh, O, Reg1);30383039if (MI->csh->detail) {3040MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3041MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;3042#ifndef CAPSTONE_DIET3043MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3044#endif3045MI->flat_insn->detail->arm.op_count++;3046}30473048SStream_concat0(O, "[]}");30493050#ifndef CAPSTONE_DIET3051MI->ac_idx++;3052#endif3053}30543055static void printVectorListThreeSpacedAllLanes(MCInst *MI,3056unsigned OpNum, SStream *O)3057{3058#ifndef CAPSTONE_DIET3059uint8_t access;30603061access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);3062#endif30633064// Normally, it's not safe to use register enum values directly with3065// addition to get the next register, but for VFP registers, the3066// sort order is guaranteed because they're all of the form D<n>.3067SStream_concat0(O, "{");30683069printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));30703071if (MI->csh->detail) {3072MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3073MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));3074#ifndef CAPSTONE_DIET3075MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3076#endif3077MI->flat_insn->detail->arm.op_count++;3078}30793080SStream_concat0(O, "[], ");30813082printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);30833084if (MI->csh->detail) {3085MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3086MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;3087#ifndef CAPSTONE_DIET3088MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3089#endif3090MI->flat_insn->detail->arm.op_count++;3091}30923093SStream_concat0(O, "[], ");30943095printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);30963097if (MI->csh->detail) {3098MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3099MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;3100#ifndef CAPSTONE_DIET3101MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3102#endif3103MI->flat_insn->detail->arm.op_count++;3104}31053106SStream_concat0(O, "[]}");31073108#ifndef CAPSTONE_DIET3109MI->ac_idx++;3110#endif3111}31123113static void printVectorListFourSpacedAllLanes(MCInst *MI,3114unsigned OpNum, SStream *O)3115{3116#ifndef CAPSTONE_DIET3117uint8_t access;31183119access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);3120#endif31213122// Normally, it's not safe to use register enum values directly with3123// addition to get the next register, but for VFP registers, the3124// sort order is guaranteed because they're all of the form D<n>.3125SStream_concat0(O, "{");31263127printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));31283129if (MI->csh->detail) {3130MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3131MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));3132#ifndef CAPSTONE_DIET3133MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3134#endif3135MI->flat_insn->detail->arm.op_count++;3136}31373138SStream_concat0(O, "[], ");31393140printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);31413142if (MI->csh->detail) {3143MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3144MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;3145#ifndef CAPSTONE_DIET3146MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3147#endif3148MI->flat_insn->detail->arm.op_count++;3149}31503151SStream_concat0(O, "[], ");31523153printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);31543155if (MI->csh->detail) {3156MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3157MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;3158#ifndef CAPSTONE_DIET3159MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3160#endif3161MI->flat_insn->detail->arm.op_count++;3162}31633164SStream_concat0(O, "[], ");31653166printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);31673168if (MI->csh->detail) {3169MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3170MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;3171#ifndef CAPSTONE_DIET3172MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3173#endif3174MI->flat_insn->detail->arm.op_count++;3175}31763177SStream_concat0(O, "[]}");31783179#ifndef CAPSTONE_DIET3180MI->ac_idx++;3181#endif3182}31833184static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O)3185{3186#ifndef CAPSTONE_DIET3187uint8_t access;31883189access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);3190#endif31913192// Normally, it's not safe to use register enum values directly with3193// addition to get the next register, but for VFP registers, the3194// sort order is guaranteed because they're all of the form D<n>.3195SStream_concat0(O, "{");31963197printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));31983199if (MI->csh->detail) {3200MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3201MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));3202#ifndef CAPSTONE_DIET3203MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3204#endif3205MI->flat_insn->detail->arm.op_count++;3206}32073208SStream_concat0(O, ", ");32093210printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);32113212if (MI->csh->detail) {3213MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3214MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;3215#ifndef CAPSTONE_DIET3216MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3217#endif3218MI->flat_insn->detail->arm.op_count++;3219}32203221SStream_concat0(O, ", ");32223223printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);32243225if (MI->csh->detail) {3226MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3227MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;3228#ifndef CAPSTONE_DIET3229MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3230#endif3231MI->flat_insn->detail->arm.op_count++;3232}32333234SStream_concat0(O, "}");32353236#ifndef CAPSTONE_DIET3237MI->ac_idx++;3238#endif3239}32403241static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O)3242{3243#ifndef CAPSTONE_DIET3244uint8_t access;32453246access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);3247#endif32483249// Normally, it's not safe to use register enum values directly with3250// addition to get the next register, but for VFP registers, the3251// sort order is guaranteed because they're all of the form D<n>.3252SStream_concat0(O, "{");32533254printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));32553256if (MI->csh->detail) {3257MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3258MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));3259#ifndef CAPSTONE_DIET3260MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3261#endif3262MI->flat_insn->detail->arm.op_count++;3263}32643265SStream_concat0(O, ", ");32663267printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);32683269if (MI->csh->detail) {3270MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3271MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;3272#ifndef CAPSTONE_DIET3273MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3274#endif3275MI->flat_insn->detail->arm.op_count++;3276}32773278SStream_concat0(O, ", ");32793280printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);32813282if (MI->csh->detail) {3283MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3284MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;3285#ifndef CAPSTONE_DIET3286MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3287#endif3288MI->flat_insn->detail->arm.op_count++;3289}32903291SStream_concat0(O, ", ");32923293printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);32943295if (MI->csh->detail) {3296MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3297MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;3298#ifndef CAPSTONE_DIET3299MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;3300#endif3301MI->flat_insn->detail->arm.op_count++;3302}33033304SStream_concat0(O, "}");33053306#ifndef CAPSTONE_DIET3307MI->ac_idx++;3308#endif3309}33103311static void printComplexRotationOp(MCInst *MI, unsigned OpNo, SStream *O, int64_t Angle, int64_t Remainder)3312{3313unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNo));3314unsigned tmp = (unsigned)((Val * Angle) + Remainder);33153316printUInt32Bang(O, tmp);3317if (MI->csh->detail) {3318MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;3319MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;3320MI->flat_insn->detail->arm.op_count++;3321}3322}33233324void ARM_addVectorDataType(MCInst *MI, arm_vectordata_type vd)3325{3326if (MI->csh->detail) {3327MI->flat_insn->detail->arm.vector_data = vd;3328}3329}33303331void ARM_addVectorDataSize(MCInst *MI, int size)3332{3333if (MI->csh->detail) {3334MI->flat_insn->detail->arm.vector_size = size;3335}3336}33373338void ARM_addReg(MCInst *MI, int reg)3339{3340if (MI->csh->detail) {3341MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;3342MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;3343MI->flat_insn->detail->arm.op_count++;3344}3345}33463347void ARM_addUserMode(MCInst *MI)3348{3349if (MI->csh->detail) {3350MI->flat_insn->detail->arm.usermode = true;3351}3352}33533354void ARM_addSysReg(MCInst *MI, arm_sysreg reg)3355{3356if (MI->csh->detail) {3357MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SYSREG;3358MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;3359MI->flat_insn->detail->arm.op_count++;3360}3361}33623363#endif336433653366