From b0e7417207af2ca1f6abcc0e81f762b562a2b2d2 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Tue, 30 May 2023 11:08:18 +0800 Subject: [PATCH] Pull auto-sync's changes from https://github.com/capstone-engine/capstone/commit/2ab11ad9bd1c7278e2eefd9998100629c3f227c7 --- CMakeLists.txt | 8 +- MCInst.c | 86 +++- MCInst.h | 24 +- MCInstrDesc.c | 20 + MCInstrDesc.h | 5 + Mapping.c | 253 +++++++++++ Mapping.h | 165 +++++++ cs_simple_types.h | 849 ++++++++++++++++++++++++++++++++++++ include/capstone/capstone.h | 15 +- utils.c | 83 ++-- utils.h | 35 +- 11 files changed, 1446 insertions(+), 97 deletions(-) create mode 100644 Mapping.c create mode 100644 Mapping.h create mode 100644 cs_simple_types.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b5c759b94..50f638c3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,9 +26,9 @@ project(capstone ) if (MSVC) - add_compile_options(/W1 /w14189 /w16268) + add_compile_options(/W1 /w14189) else() - add_compile_options(-Wunused-function -Warray-bounds -Wunused-variable -Wparentheses -Wint-in-bool-context) + add_compile_options(-Wmissing-braces -Wunused-function -Warray-bounds -Wunused-variable -Wparentheses -Wint-in-bool-context) endif() @@ -98,6 +98,7 @@ endif() ## sources set(SOURCES_ENGINE cs.c + Mapping.c MCInst.c MCInstrDesc.c MCRegisterInfo.c @@ -105,8 +106,10 @@ set(SOURCES_ENGINE utils.c ) set(HEADERS_ENGINE + cs_simple_types.h cs_priv.h LEB128.h + Mapping.h MathExtras.h MCDisassembler.h MCFixedLenDisassembler.h @@ -549,7 +552,6 @@ if (CAPSTONE_TRICORE_SUPPORT) arch/TriCore/TriCoreGenDisassemblerTables.inc arch/TriCore/TriCoreGenInstrInfo.inc arch/TriCore/TriCoreGenRegisterInfo.inc - arch/TriCore/TriCoreInstPrinter.h arch/TriCore/TriCoreMapping.h arch/TriCore/TriCoreModule.h ) diff --git a/MCInst.c b/MCInst.c index c41be1488..a5741386e 100644 --- a/MCInst.c +++ b/MCInst.c @@ -9,6 +9,7 @@ #include #endif #include +#include #include "MCInst.h" #include "utils.h" @@ -32,6 +33,8 @@ void MCInst_Init(MCInst *inst) inst->assembly[0] = '\0'; inst->wasm_data.type = WASM_OP_INVALID; inst->xAcquireRelease = 0; + for (int i = 0; i < MAX_MC_OPS; ++i) + inst->tied_op_idx[i] = -1; } void MCInst_clear(MCInst *inst) @@ -39,9 +42,10 @@ void MCInst_clear(MCInst *inst) inst->size = 0; } -// do not free @Op +// does not free @Op void MCInst_insert0(MCInst *inst, int index, MCOperand *Op) { + assert(index < MAX_MC_OPS); int i; for(i = inst->size; i > index; i--) @@ -74,6 +78,7 @@ unsigned MCInst_getOpcodePub(const MCInst *inst) MCOperand *MCInst_getOperand(MCInst *inst, unsigned i) { + assert(i < MAX_MC_OPS); return &inst->Operands[i]; } @@ -85,6 +90,7 @@ unsigned MCInst_getNumOperands(const MCInst *inst) // This addOperand2 function doesnt free Op void MCInst_addOperand2(MCInst *inst, MCOperand *Op) { + assert(inst->size < MAX_MC_OPS); inst->Operands[inst->size] = *Op; inst->size++; @@ -110,6 +116,21 @@ bool MCOperand_isFPImm(const MCOperand *op) return op->Kind == kFPImmediate; } +bool MCOperand_isDFPImm(const MCOperand *op) +{ + return op->Kind == kDFPImmediate; +} + +bool MCOperand_isExpr(const MCOperand *op) +{ + return op->Kind == kExpr; +} + +bool MCOperand_isInst(const MCOperand *op) +{ + return op->Kind == kInst; +} + /// getReg - Returns the register number. unsigned MCOperand_getReg(const MCOperand *op) { @@ -146,6 +167,7 @@ MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg) { MCOperand *op = &(mcInst->Operands[MCINST_CACHE]); + op->MachineOperandType = kRegister; op->Kind = kRegister; op->RegVal = Reg; @@ -157,6 +179,7 @@ void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg) MCOperand *op = &(mcInst->Operands[mcInst->size]); mcInst->size++; + op->MachineOperandType = kRegister; op->Kind = kRegister; op->RegVal = Reg; } @@ -165,6 +188,7 @@ MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val) { MCOperand *op = &(mcInst->Operands[MCINST_CACHE]); + op->MachineOperandType = kImmediate; op->Kind = kImmediate; op->ImmVal = Val; @@ -173,9 +197,69 @@ MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val) void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val) { + assert(mcInst->size < MAX_MC_OPS); MCOperand *op = &(mcInst->Operands[mcInst->size]); mcInst->size++; + op->MachineOperandType = kImmediate; op->Kind = kImmediate; op->ImmVal = Val; } + +/// Check if any operand of the MCInstrDesc is predicable +bool MCInst_isPredicable(const MCInstrDesc *MIDesc) { + const MCOperandInfo *OpInfo = MIDesc->OpInfo; + unsigned NumOps = MIDesc->NumOperands; + for (unsigned i = 0; i < NumOps; ++i) { + if (MCOperandInfo_isPredicate(&OpInfo[i])) { + return true; + } + } + return false; +} + +/// Checks if tied operands exist in the instruction and sets +/// - The writeback flag in detail +/// - Saves the indices of the tied destination operands. +void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc) { + const MCOperandInfo *OpInfo = InstDesc[MCInst_getOpcode(MI)].OpInfo; + unsigned short NumOps = InstDesc[MCInst_getOpcode(MI)].NumOperands; + + unsigned i; + for (i = 0; i < NumOps; ++i) { + if (MCOperandInfo_isTiedToOp(&OpInfo[i])) { + int idx = MCOperandInfo_getOperandConstraint( + &InstDesc[MCInst_getOpcode(MI)], i, MCOI_TIED_TO); + + if (idx == -1) + continue; + + if(i >= MAX_MC_OPS) { + assert(0 && "Maximum number of MC operands reached."); + } + MI->tied_op_idx[i] = idx; + + if (MI->flat_insn->detail) + MI->flat_insn->detail->writeback = true; + } + } +} + +/// Check if operand with OpNum is tied by another operand +/// (operand is tying destination). +bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum) { + assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded."); + for (int i = 0; i < MAX_MC_OPS; ++i) { + if (MI->tied_op_idx[i] == OpNum) + return true; + } + return false; +} + +/// Check if operand with OpNum is tying another operand +/// (operand is tying src). +bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum) { + assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded."); + return MI->tied_op_idx[OpNum] != -1; +} + diff --git a/MCInst.h b/MCInst.h index 2e5df7426..49bc03b87 100644 --- a/MCInst.h +++ b/MCInst.h @@ -20,6 +20,7 @@ #define CS_MCINST_H #include "include/capstone/capstone.h" +#include "MCInstrDesc.h" #include "MCRegisterInfo.h" typedef struct MCInst MCInst; @@ -34,6 +35,10 @@ struct MCOperand { kRegister, ///< Register operand. kImmediate, ///< Immediate operand. kFPImmediate, ///< Floating-point immediate operand. + kDFPImmediate, ///< Double-Floating-point immediate operand. + kExpr, ///< Relocatable immediate operand. + kInst ///< Sub-instruction operand. + } MachineOperandType; unsigned char Kind; @@ -52,6 +57,10 @@ bool MCOperand_isImm(const MCOperand *op); bool MCOperand_isFPImm(const MCOperand *op); +bool MCOperand_isDFPImm(const MCOperand *op); + +bool MCOperand_isExpr(const MCOperand *op); + bool MCOperand_isInst(const MCOperand *op); /// getReg - Returns the register number. @@ -84,6 +93,8 @@ void MCOperand_CreateImm0(MCInst *inst, int64_t Val); // create Imm operand in the last-unused slot MCOperand *MCOperand_CreateImm1(MCInst *inst, int64_t Val); +#define MAX_MC_OPS 48 + /// MCInst - Instances of this class represent a single low-level machine /// instruction. struct MCInst { @@ -92,7 +103,7 @@ struct MCInst { bool has_imm; // indicate this instruction has an X86_OP_IMM operand - used for ATT syntax uint8_t op1_size; // size of 1st operand - for X86 Intel syntax unsigned Opcode; // private opcode - MCOperand Operands[48]; + MCOperand Operands[MAX_MC_OPS]; cs_insn *flat_insn; // insn to be exposed to public uint64_t address; // address of this insn cs_struct *csh; // save the main csh @@ -108,7 +119,8 @@ struct MCInst { // This is copied from cs_x86 struct uint8_t x86_prefix[4]; uint8_t imm_size; // immediate size for X86_OP_IMM operand - bool writeback; // writeback for ARM + bool writeback; // writeback for ARM + int8_t tied_op_idx[MAX_MC_OPS]; ///< Tied operand indices. Index = Src op; Value: Dest op // operand access index for list of registers sharing the same access right (for ARM) uint8_t ac_idx; uint8_t popcode_adjust; // Pseudo X86 instruction adjust @@ -141,4 +153,12 @@ unsigned MCInst_getNumOperands(const MCInst *inst); // This addOperand2 function doesnt free Op void MCInst_addOperand2(MCInst *inst, MCOperand *Op); +bool MCInst_isPredicable(const MCInstrDesc *MIDesc); + +void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc); + +bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum); + +bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum); + #endif diff --git a/MCInstrDesc.c b/MCInstrDesc.c index 9bb264a43..f2fed8b0e 100644 --- a/MCInstrDesc.c +++ b/MCInstrDesc.c @@ -16,3 +16,23 @@ bool MCOperandInfo_isOptionalDef(const MCOperandInfo *m) { return m->Flags & (1 << MCOI_OptionalDef); } + +/// Checks if operand is tied to another one. +bool MCOperandInfo_isTiedToOp(const MCOperandInfo *m) { + if (m->Constraints & (1 << MCOI_TIED_TO)) + return true; + return false; +} + +/// Returns the value of the specified operand constraint if +/// it is present. Returns -1 if it is not present. +int MCOperandInfo_getOperandConstraint(const MCInstrDesc *InstrDesc, unsigned OpNum, + MCOI_OperandConstraint Constraint) { + const MCOperandInfo OpInfo = InstrDesc->OpInfo[OpNum]; + if (OpNum < InstrDesc->NumOperands && + (OpInfo.Constraints & (1 << Constraint))) { + unsigned ValuePos = 4 + Constraint * 4; + return (OpInfo.Constraints >> ValuePos) & 0xf; + } + return -1; +} \ No newline at end of file diff --git a/MCInstrDesc.h b/MCInstrDesc.h index f97555308..7c1097754 100644 --- a/MCInstrDesc.h +++ b/MCInstrDesc.h @@ -158,4 +158,9 @@ bool MCOperandInfo_isPredicate(const MCOperandInfo *m); bool MCOperandInfo_isOptionalDef(const MCOperandInfo *m); +bool MCOperandInfo_isTiedToOp(const MCOperandInfo *m); + +int MCOperandInfo_getOperandConstraint(const MCInstrDesc *OpInfo, unsigned OpNum, + MCOI_OperandConstraint Constraint); + #endif diff --git a/Mapping.c b/Mapping.c new file mode 100644 index 000000000..a90278614 --- /dev/null +++ b/Mapping.c @@ -0,0 +1,253 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh , 2013-2019 */ +/* Rot127 , 2022-2023 */ + +#include "Mapping.h" + +// create a cache for fast id lookup +static unsigned short *make_id2insn(const insn_map *insns, unsigned int size) +{ + // NOTE: assume that the max id is always put at the end of insns array + unsigned short max_id = insns[size - 1].id; + unsigned short i; + + unsigned short *cache = + (unsigned short *)cs_mem_calloc(max_id + 1, sizeof(*cache)); + + for (i = 1; i < size; i++) + cache[insns[i].id] = i; + + return cache; +} + +// look for @id in @insns, given its size in @max. first time call will update +// @cache. return 0 if not found +unsigned short insn_find(const insn_map *insns, unsigned int max, + unsigned int id, unsigned short **cache) +{ + if (id > insns[max - 1].id) + return 0; + + if (*cache == NULL) + *cache = make_id2insn(insns, max); + + return (*cache)[id]; +} + +// Gives the id for the given @name if it is saved in @map. +// Returns the id or -1 if not found. +int name2id(const name_map *map, int max, const char *name) +{ + int i; + + for (i = 0; i < max; i++) { + if (!strcmp(map[i].name, name)) { + return map[i].id; + } + } + + // nothing match + return -1; +} + +// Gives the name for the given @id if it is saved in @map. +// Returns the name or NULL if not found. +const char *id2name(const name_map *map, int max, const unsigned int id) +{ + int i; + + for (i = 0; i < max; i++) { + if (map[i].id == id) { + return map[i].name; + } + } + + // nothing match + return NULL; +} + +/// Adds a register to the implicit write register list. +/// It will not add the same register twice. +void map_add_implicit_write(MCInst *MI, uint32_t Reg) +{ + if (!MI->flat_insn->detail) + return; + + uint16_t *regs_write = MI->flat_insn->detail->regs_write; + for (int i = 0; i < MAX_IMPL_W_REGS; ++i) { + if (i == MI->flat_insn->detail->regs_write_count) { + regs_write[i] = Reg; + MI->flat_insn->detail->regs_write_count++; + return; + } + if (regs_write[i] == Reg) + return; + } +} + +/// Copies the implicit read registers of @imap to @MI->flat_insn. +/// Already present registers will be preserved. +void map_implicit_reads(MCInst *MI, const insn_map *imap) +{ +#ifndef CAPSTONE_DIET + if (!MI->flat_insn->detail) + return; + + cs_detail *detail = MI->flat_insn->detail; + unsigned Opcode = MCInst_getOpcode(MI); + unsigned i = 0; + uint16_t reg = imap[Opcode].regs_use[i]; + while (reg != 0) { + if (i >= MAX_IMPL_R_REGS || + detail->regs_read_count >= MAX_IMPL_R_REGS) { + printf("ERROR: Too many implicit read register defined in " + "instruction mapping.\n"); + return; + } + detail->regs_read[detail->regs_read_count++] = reg; + reg = imap[Opcode].regs_use[++i]; + } +#endif // CAPSTONE_DIET +} + +/// Copies the implicit write registers of @imap to @MI->flat_insn. +/// Already present registers will be preserved. +void map_implicit_writes(MCInst *MI, const insn_map *imap) +{ +#ifndef CAPSTONE_DIET + if (!MI->flat_insn->detail) + return; + + cs_detail *detail = MI->flat_insn->detail; + unsigned Opcode = MCInst_getOpcode(MI); + unsigned i = 0; + uint16_t reg = imap[Opcode].regs_mod[i]; + while (reg != 0) { + if (i >= MAX_IMPL_W_REGS || + detail->regs_write_count >= MAX_IMPL_W_REGS) { + printf("ERROR: Too many implicit write register defined in " + "instruction mapping.\n"); + return; + } + detail->regs_write[detail->regs_write_count++] = reg; + reg = imap[Opcode].regs_mod[++i]; + } +#endif // CAPSTONE_DIET +} + +/// Copies the groups from @imap to @MI->flat_insn. +/// Already present groups will be preserved. +void map_groups(MCInst *MI, const insn_map *imap) +{ +#ifndef CAPSTONE_DIET + if (!MI->flat_insn->detail) + return; + + cs_detail *detail = MI->flat_insn->detail; + unsigned Opcode = MCInst_getOpcode(MI); + unsigned i = 0; + uint16_t group = imap[Opcode].groups[i]; + while (group != 0) { + if (detail->groups_count >= MAX_NUM_GROUPS) { + printf("ERROR: Too many groups defined in instruction mapping.\n"); + return; + } + detail->groups[detail->groups_count++] = group; + group = imap[Opcode].groups[++i]; + } +#endif // CAPSTONE_DIET +} + +// Search for the CS instruction id for the given @MC_Opcode in @imap. +// return -1 if none is found. +unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap, + unsigned imap_size) +{ + // binary searching since the IDs are sorted in order + unsigned int left, right, m; + unsigned int max = imap_size; + + right = max - 1; + + if (MC_Opcode < imap[0].id || MC_Opcode > imap[right].id) + // not found + return -1; + + left = 0; + + while (left <= right) { + m = (left + right) / 2; + if (MC_Opcode == imap[m].id) { + return m; + } + + if (MC_Opcode < imap[m].id) + right = m - 1; + else + left = m + 1; + } + + return -1; +} + +/// Sets the Capstone instruction id which maps to the @MI opcode. +/// If no mapping is found the function returns and prints an error. +void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size) +{ + unsigned int i = find_cs_id(MCInst_getOpcode(MI), imap, imap_size); + if (i != -1) { + MI->flat_insn->id = imap[i].mapid; + return; + } + printf("ERROR: Could not find CS id for MCInst opcode: %d\n", + MCInst_getOpcode(MI)); + return; +} + +/// Returns the operand type information from the +/// mapping table for instruction operands. +/// Only usable by `auto-sync` archs! +const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum, + const map_insn_ops *insn_ops_map, + size_t map_size) +{ + assert(MI); + assert(MI->Opcode < map_size); + assert(OpNum < sizeof(insn_ops_map[MI->Opcode].ops) / + sizeof(insn_ops_map[MI->Opcode].ops[0])); + + return insn_ops_map[MI->Opcode].ops[OpNum].type; +} + +/// Returns the operand access flags from the +/// mapping table for instruction operands. +/// Only usable by `auto-sync` archs! +const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum, + const map_insn_ops *insn_ops_map, + size_t map_size) +{ + assert(MI); + assert(MI->Opcode < map_size); + assert(OpNum < sizeof(insn_ops_map[MI->Opcode].ops) / + sizeof(insn_ops_map[MI->Opcode].ops[0])); + + cs_ac_type access = insn_ops_map[MI->Opcode].ops[OpNum].access; + if (MCInst_opIsTied(MI, OpNum) || MCInst_opIsTying(MI, OpNum)) + access |= (access == CS_AC_READ) ? CS_AC_WRITE : CS_AC_READ; + return access; +} + +/// Returns the operand at detail->arch.operands[op_count + offset] +/// Or NULL if detail is not set. +#define DEFINE_get_detail_op(arch, ARCH) \ + cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset) \ + { \ + if (!MI->flat_insn->detail) \ + return NULL; \ + int OpIdx = MI->flat_insn->detail->arch.op_count + offset; \ + assert(OpIdx >= 0 && OpIdx < MAX_MC_OPS); \ + return &MI->flat_insn->detail->arch.operands[OpIdx]; \ + } + +DEFINE_get_detail_op(arm, ARM); +DEFINE_get_detail_op(ppc, PPC); diff --git a/Mapping.h b/Mapping.h new file mode 100644 index 000000000..1ef491c26 --- /dev/null +++ b/Mapping.h @@ -0,0 +1,165 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh , 2013-2019 */ +/* Rot127 , 2022-2023 */ + +#ifndef CS_MAPPING_H +#define CS_MAPPING_H + +#if defined(CAPSTONE_HAS_OSXKERNEL) +#include +#else +#include "include/capstone/capstone.h" +#include +#endif +#include "cs_priv.h" +#include +#include + +// map instruction to its characteristics +typedef struct insn_map { + unsigned short id; // The LLVM instruction id + unsigned short mapid; // The Capstone instruction id +#ifndef CAPSTONE_DIET + uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by + ///< this instruction + uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified + ///< by this instruction + unsigned char + groups[MAX_NUM_GROUPS]; ///< list of group this instruction belong to + bool branch; // branch instruction? + bool indirect_branch; // indirect branch instruction? +#endif +} insn_map; + +// look for @id in @m, given its size in @max. first time call will update +// @cache. return 0 if not found +unsigned short insn_find(const insn_map *m, unsigned int max, unsigned int id, + unsigned short **cache); + +unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap, + unsigned imap_size); + +#define MAX_NO_DATA_TYPES 10 + +///< A LLVM<->CS Mapping entry of an MCOperand. +typedef struct { + uint8_t /* cs_op_type */ type; ///< Operand type (e.g.: reg, imm, mem) + uint8_t /* cs_ac_type */ access; ///< The access type (read, write) + uint8_t /* cs_data_type */ + dtypes[MAX_NO_DATA_TYPES]; ///< List of op types. Terminated by + ///< CS_DATA_TYPE_LAST +} mapping_op; + +#define MAX_NO_INSN_MAP_OPS 16 + +///< MCOperands of an instruction. +typedef struct { + mapping_op ops[MAX_NO_INSN_MAP_OPS]; ///< NULL terminated array of insn_op. +} map_insn_ops; + +/// Only usable by `auto-sync` archs! +const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum, + const map_insn_ops *insn_ops_map, + size_t map_size); + +/// Only usable by `auto-sync` archs! +const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum, + const map_insn_ops *insn_ops_map, + size_t map_size); + +/// Macro for easier access of operand types from the map. +/// Assumes the istruction operands map is called "insn_operands" +/// Only usable by `auto-sync` archs! +#define map_get_op_type(MI, OpNum) \ + mapping_get_op_type(MI, OpNum, insn_operands, \ + sizeof(insn_operands) / sizeof(insn_operands[0])) + +/// Macro for easier access of operand access flags from the map. +/// Assumes the istruction operands map is called "insn_operands" +/// Only usable by `auto-sync` archs! +#define map_get_op_access(MI, OpNum) \ + mapping_get_op_access(MI, OpNum, insn_operands, \ + sizeof(insn_operands) / sizeof(insn_operands[0])) + +///< Map for ids to their string +typedef struct name_map { + unsigned int id; + const char *name; +} name_map; + +// map a name to its ID +// return 0 if not found +int name2id(const name_map *map, int max, const char *name); + +// map ID to a name +// return NULL if not found +const char *id2name(const name_map *map, int max, const unsigned int id); + +void map_add_implicit_write(MCInst *MI, uint32_t Reg); + +void map_implicit_reads(MCInst *MI, const insn_map *imap); + +void map_implicit_writes(MCInst *MI, const insn_map *imap); + +void map_groups(MCInst *MI, const insn_map *imap); + +void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size); + +#define DECL_get_detail_op(arch, ARCH) \ + cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset); + +DECL_get_detail_op(arm, ARM); +DECL_get_detail_op(ppc, PPC); + +/// Increments the detail->arch.op_count by one. +#define DEFINE_inc_detail_op_count(arch, ARCH) \ + static inline void ARCH##_inc_op_count(MCInst *MI) \ + { \ + MI->flat_insn->detail->arch.op_count++; \ + } + +/// Decrements the detail->arch.op_count by one. +#define DEFINE_dec_detail_op_count(arch, ARCH) \ + static inline void ARCH##_dec_op_count(MCInst *MI) \ + { \ + MI->flat_insn->detail->arch.op_count--; \ + } + +DEFINE_inc_detail_op_count(arm, ARM); +DEFINE_dec_detail_op_count(arm, ARM); +DEFINE_inc_detail_op_count(ppc, PPC); +DEFINE_dec_detail_op_count(ppc, PPC); + +/// Returns true if a memory operand is currently edited. +static inline bool doing_mem(const MCInst *MI) { return MI->csh->doing_mem; } + +/// Sets the doing_mem flag to @status. +static inline void set_doing_mem(const MCInst *MI, bool status) +{ + MI->csh->doing_mem = status; +} + +/// Returns detail->arch +#define DEFINE_get_arch_detail(arch, ARCH) \ + static inline cs_##arch *ARCH##_get_detail(const MCInst *MI) \ + { \ + assert(MI && MI->flat_insn && MI->flat_insn->detail); \ + return &MI->flat_insn->detail->arch; \ + } + +DEFINE_get_arch_detail(arm, ARM); +DEFINE_get_arch_detail(ppc, PPC); + +static inline bool detail_is_set(const MCInst *MI) +{ + assert(MI && MI->flat_insn); + return MI->flat_insn->detail != NULL; +} + +static inline cs_detail *get_detail(const MCInst *MI) +{ + assert(MI && MI->flat_insn); + return MI->flat_insn->detail; +} + +#endif // CS_MAPPING_H \ No newline at end of file diff --git a/cs_simple_types.h b/cs_simple_types.h new file mode 100644 index 000000000..a3b0c090e --- /dev/null +++ b/cs_simple_types.h @@ -0,0 +1,849 @@ +/* Capstone Disassembly Engine, https://www.capstone-engine.org */ +/* By Nguyen Anh Quynh , 2013-2019 */ +/* By Rot127 , 2023 */ + +/* This header file mirrors LLVMs MachineValueTypes.h. */ + +#ifndef CS_SIMPLE_TYPES_H +#define CS_SIMPLE_TYPES_H + +#include +#include + +typedef enum { + + // Simple value types that aren't explicitly part of this enumeration + // are considered extended value types. + CS_DATA_TYPE_INVALID_SIMPLE_VALUE_TYPE = 0, + + // If you change this numbering, you must change the values in + // ValueTypes.td as well! + CS_DATA_TYPE_Other = 1, // This is a non-standard value + CS_DATA_TYPE_i1 = 2, // This is a 1 bit integer value + CS_DATA_TYPE_i2 = 3, // This is a 2 bit integer value + CS_DATA_TYPE_i4 = 4, // This is a 4 bit integer value + CS_DATA_TYPE_i8 = 5, // This is an 8 bit integer value + CS_DATA_TYPE_i16 = 6, // This is a 16 bit integer value + CS_DATA_TYPE_i32 = 7, // This is a 32 bit integer value + CS_DATA_TYPE_i64 = 8, // This is a 64 bit integer value + CS_DATA_TYPE_i128 = 9, // This is a 128 bit integer value + + CS_DATA_TYPE_FIRST_INTEGER_VALUETYPE = CS_DATA_TYPE_i1, + CS_DATA_TYPE_LAST_INTEGER_VALUETYPE = CS_DATA_TYPE_i128, + + CS_DATA_TYPE_bf16 = 10, // This is a 16 bit brain floating point value + CS_DATA_TYPE_f16 = 11, // This is a 16 bit floating point value + CS_DATA_TYPE_f32 = 12, // This is a 32 bit floating point value + CS_DATA_TYPE_f64 = 13, // This is a 64 bit floating point value + CS_DATA_TYPE_f80 = 14, // This is a 80 bit floating point value + CS_DATA_TYPE_f128 = 15, // This is a 128 bit floating point value + CS_DATA_TYPE_ppcf128 = 16, // This is a PPC 128-bit floating point value + + CS_DATA_TYPE_FIRST_FP_VALUETYPE = CS_DATA_TYPE_bf16, + CS_DATA_TYPE_LAST_FP_VALUETYPE = CS_DATA_TYPE_ppcf128, + + CS_DATA_TYPE_v1i1 = 17, // 1 x i1 + CS_DATA_TYPE_v2i1 = 18, // 2 x i1 + CS_DATA_TYPE_v4i1 = 19, // 4 x i1 + CS_DATA_TYPE_v8i1 = 20, // 8 x i1 + CS_DATA_TYPE_v16i1 = 21, // 16 x i1 + CS_DATA_TYPE_v32i1 = 22, // 32 x i1 + CS_DATA_TYPE_v64i1 = 23, // 64 x i1 + CS_DATA_TYPE_v128i1 = 24, // 128 x i1 + CS_DATA_TYPE_v256i1 = 25, // 256 x i1 + CS_DATA_TYPE_v512i1 = 26, // 512 x i1 + CS_DATA_TYPE_v1024i1 = 27, // 1024 x i1 + CS_DATA_TYPE_v2048i1 = 28, // 2048 x i1 + + CS_DATA_TYPE_v128i2 = 29, // 128 x i2 + CS_DATA_TYPE_v256i2 = 30, // 256 x i2 + + CS_DATA_TYPE_v64i4 = 31, // 64 x i4 + CS_DATA_TYPE_v128i4 = 32, // 128 x i4 + + CS_DATA_TYPE_v1i8 = 33, // 1 x i8 + CS_DATA_TYPE_v2i8 = 34, // 2 x i8 + CS_DATA_TYPE_v4i8 = 35, // 4 x i8 + CS_DATA_TYPE_v8i8 = 36, // 8 x i8 + CS_DATA_TYPE_v16i8 = 37, // 16 x i8 + CS_DATA_TYPE_v32i8 = 38, // 32 x i8 + CS_DATA_TYPE_v64i8 = 39, // 64 x i8 + CS_DATA_TYPE_v128i8 = 40, // 128 x i8 + CS_DATA_TYPE_v256i8 = 41, // 256 x i8 + CS_DATA_TYPE_v512i8 = 42, // 512 x i8 + CS_DATA_TYPE_v1024i8 = 43, // 1024 x i8 + + CS_DATA_TYPE_v1i16 = 44, // 1 x i16 + CS_DATA_TYPE_v2i16 = 45, // 2 x i16 + CS_DATA_TYPE_v3i16 = 46, // 3 x i16 + CS_DATA_TYPE_v4i16 = 47, // 4 x i16 + CS_DATA_TYPE_v8i16 = 48, // 8 x i16 + CS_DATA_TYPE_v16i16 = 49, // 16 x i16 + CS_DATA_TYPE_v32i16 = 50, // 32 x i16 + CS_DATA_TYPE_v64i16 = 51, // 64 x i16 + CS_DATA_TYPE_v128i16 = 52, // 128 x i16 + CS_DATA_TYPE_v256i16 = 53, // 256 x i16 + CS_DATA_TYPE_v512i16 = 54, // 512 x i16 + + CS_DATA_TYPE_v1i32 = 55, // 1 x i32 + CS_DATA_TYPE_v2i32 = 56, // 2 x i32 + CS_DATA_TYPE_v3i32 = 57, // 3 x i32 + CS_DATA_TYPE_v4i32 = 58, // 4 x i32 + CS_DATA_TYPE_v5i32 = 59, // 5 x i32 + CS_DATA_TYPE_v6i32 = 60, // 6 x i32 + CS_DATA_TYPE_v7i32 = 61, // 7 x i32 + CS_DATA_TYPE_v8i32 = 62, // 8 x i32 + CS_DATA_TYPE_v9i32 = 63, // 9 x i32 + CS_DATA_TYPE_v10i32 = 64, // 10 x i32 + CS_DATA_TYPE_v11i32 = 65, // 11 x i32 + CS_DATA_TYPE_v12i32 = 66, // 12 x i32 + CS_DATA_TYPE_v16i32 = 67, // 16 x i32 + CS_DATA_TYPE_v32i32 = 68, // 32 x i32 + CS_DATA_TYPE_v64i32 = 69, // 64 x i32 + CS_DATA_TYPE_v128i32 = 70, // 128 x i32 + CS_DATA_TYPE_v256i32 = 71, // 256 x i32 + CS_DATA_TYPE_v512i32 = 72, // 512 x i32 + CS_DATA_TYPE_v1024i32 = 73, // 1024 x i32 + CS_DATA_TYPE_v2048i32 = 74, // 2048 x i32 + + CS_DATA_TYPE_v1i64 = 75, // 1 x i64 + CS_DATA_TYPE_v2i64 = 76, // 2 x i64 + CS_DATA_TYPE_v3i64 = 77, // 3 x i64 + CS_DATA_TYPE_v4i64 = 78, // 4 x i64 + CS_DATA_TYPE_v8i64 = 79, // 8 x i64 + CS_DATA_TYPE_v16i64 = 80, // 16 x i64 + CS_DATA_TYPE_v32i64 = 81, // 32 x i64 + CS_DATA_TYPE_v64i64 = 82, // 64 x i64 + CS_DATA_TYPE_v128i64 = 83, // 128 x i64 + CS_DATA_TYPE_v256i64 = 84, // 256 x i64 + + CS_DATA_TYPE_v1i128 = 85, // 1 x i128 + + CS_DATA_TYPE_FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = CS_DATA_TYPE_v1i1, + CS_DATA_TYPE_LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = CS_DATA_TYPE_v1i128, + + CS_DATA_TYPE_v1f16 = 86, // 1 x f16 + CS_DATA_TYPE_v2f16 = 87, // 2 x f16 + CS_DATA_TYPE_v3f16 = 88, // 3 x f16 + CS_DATA_TYPE_v4f16 = 89, // 4 x f16 + CS_DATA_TYPE_v8f16 = 90, // 8 x f16 + CS_DATA_TYPE_v16f16 = 91, // 16 x f16 + CS_DATA_TYPE_v32f16 = 92, // 32 x f16 + CS_DATA_TYPE_v64f16 = 93, // 64 x f16 + CS_DATA_TYPE_v128f16 = 94, // 128 x f16 + CS_DATA_TYPE_v256f16 = 95, // 256 x f16 + CS_DATA_TYPE_v512f16 = 96, // 512 x f16 + + CS_DATA_TYPE_v2bf16 = 97, // 2 x bf16 + CS_DATA_TYPE_v3bf16 = 98, // 3 x bf16 + CS_DATA_TYPE_v4bf16 = 99, // 4 x bf16 + CS_DATA_TYPE_v8bf16 = 100, // 8 x bf16 + CS_DATA_TYPE_v16bf16 = 101, // 16 x bf16 + CS_DATA_TYPE_v32bf16 = 102, // 32 x bf16 + CS_DATA_TYPE_v64bf16 = 103, // 64 x bf16 + CS_DATA_TYPE_v128bf16 = 104, // 128 x bf16 + + CS_DATA_TYPE_v1f32 = 105, // 1 x f32 + CS_DATA_TYPE_v2f32 = 106, // 2 x f32 + CS_DATA_TYPE_v3f32 = 107, // 3 x f32 + CS_DATA_TYPE_v4f32 = 108, // 4 x f32 + CS_DATA_TYPE_v5f32 = 109, // 5 x f32 + CS_DATA_TYPE_v6f32 = 110, // 6 x f32 + CS_DATA_TYPE_v7f32 = 111, // 7 x f32 + CS_DATA_TYPE_v8f32 = 112, // 8 x f32 + CS_DATA_TYPE_v9f32 = 113, // 9 x f32 + CS_DATA_TYPE_v10f32 = 114, // 10 x f32 + CS_DATA_TYPE_v11f32 = 115, // 11 x f32 + CS_DATA_TYPE_v12f32 = 116, // 12 x f32 + CS_DATA_TYPE_v16f32 = 117, // 16 x f32 + + CS_DATA_TYPE_v32f32 = 118, // 32 x f32 + CS_DATA_TYPE_v64f32 = 119, // 64 x f32 + CS_DATA_TYPE_v128f32 = 120, // 128 x f32 + CS_DATA_TYPE_v256f32 = 121, // 256 x f32 + CS_DATA_TYPE_v512f32 = 122, // 512 x f32 + CS_DATA_TYPE_v1024f32 = 123, // 1024 x f32 + CS_DATA_TYPE_v2048f32 = 124, // 2048 x f32 + + CS_DATA_TYPE_v1f64 = 125, // 1 x f64 + CS_DATA_TYPE_v2f64 = 126, // 2 x f64 + CS_DATA_TYPE_v3f64 = 127, // 3 x f64 + CS_DATA_TYPE_v4f64 = 128, // 4 x f64 + CS_DATA_TYPE_v8f64 = 129, // 8 x f64 + CS_DATA_TYPE_v16f64 = 130, // 16 x f64 + CS_DATA_TYPE_v32f64 = 131, // 32 x f64 + CS_DATA_TYPE_v64f64 = 132, // 64 x f64 + CS_DATA_TYPE_v128f64 = 133, // 128 x f64 + CS_DATA_TYPE_v256f64 = 134, // 256 x f64 + + CS_DATA_TYPE_FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE = CS_DATA_TYPE_v1f16, + CS_DATA_TYPE_LAST_FP_FIXEDLEN_VECTOR_VALUETYPE = CS_DATA_TYPE_v256f64, + + CS_DATA_TYPE_FIRST_FIXEDLEN_VECTOR_VALUETYPE = CS_DATA_TYPE_v1i1, + CS_DATA_TYPE_LAST_FIXEDLEN_VECTOR_VALUETYPE = CS_DATA_TYPE_v256f64, + + CS_DATA_TYPE_nxv1i1 = 135, // n x 1 x i1 + CS_DATA_TYPE_nxv2i1 = 136, // n x 2 x i1 + CS_DATA_TYPE_nxv4i1 = 137, // n x 4 x i1 + CS_DATA_TYPE_nxv8i1 = 138, // n x 8 x i1 + CS_DATA_TYPE_nxv16i1 = 139, // n x 16 x i1 + CS_DATA_TYPE_nxv32i1 = 140, // n x 32 x i1 + CS_DATA_TYPE_nxv64i1 = 141, // n x 64 x i1 + + CS_DATA_TYPE_nxv1i8 = 142, // n x 1 x i8 + CS_DATA_TYPE_nxv2i8 = 143, // n x 2 x i8 + CS_DATA_TYPE_nxv4i8 = 144, // n x 4 x i8 + CS_DATA_TYPE_nxv8i8 = 145, // n x 8 x i8 + CS_DATA_TYPE_nxv16i8 = 146, // n x 16 x i8 + CS_DATA_TYPE_nxv32i8 = 147, // n x 32 x i8 + CS_DATA_TYPE_nxv64i8 = 148, // n x 64 x i8 + + CS_DATA_TYPE_nxv1i16 = 149, // n x 1 x i16 + CS_DATA_TYPE_nxv2i16 = 150, // n x 2 x i16 + CS_DATA_TYPE_nxv4i16 = 151, // n x 4 x i16 + CS_DATA_TYPE_nxv8i16 = 152, // n x 8 x i16 + CS_DATA_TYPE_nxv16i16 = 153, // n x 16 x i16 + CS_DATA_TYPE_nxv32i16 = 154, // n x 32 x i16 + + CS_DATA_TYPE_nxv1i32 = 155, // n x 1 x i32 + CS_DATA_TYPE_nxv2i32 = 156, // n x 2 x i32 + CS_DATA_TYPE_nxv4i32 = 157, // n x 4 x i32 + CS_DATA_TYPE_nxv8i32 = 158, // n x 8 x i32 + CS_DATA_TYPE_nxv16i32 = 159, // n x 16 x i32 + CS_DATA_TYPE_nxv32i32 = 160, // n x 32 x i32 + + CS_DATA_TYPE_nxv1i64 = 161, // n x 1 x i64 + CS_DATA_TYPE_nxv2i64 = 162, // n x 2 x i64 + CS_DATA_TYPE_nxv4i64 = 163, // n x 4 x i64 + CS_DATA_TYPE_nxv8i64 = 164, // n x 8 x i64 + CS_DATA_TYPE_nxv16i64 = 165, // n x 16 x i64 + CS_DATA_TYPE_nxv32i64 = 166, // n x 32 x i64 + + CS_DATA_TYPE_FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv1i1, + CS_DATA_TYPE_LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv32i64, + + CS_DATA_TYPE_nxv1f16 = 167, // n x 1 x f16 + CS_DATA_TYPE_nxv2f16 = 168, // n x 2 x f16 + CS_DATA_TYPE_nxv4f16 = 169, // n x 4 x f16 + CS_DATA_TYPE_nxv8f16 = 170, // n x 8 x f16 + CS_DATA_TYPE_nxv16f16 = 171, // n x 16 x f16 + CS_DATA_TYPE_nxv32f16 = 172, // n x 32 x f16 + + CS_DATA_TYPE_nxv1bf16 = 173, // n x 1 x bf16 + CS_DATA_TYPE_nxv2bf16 = 174, // n x 2 x bf16 + CS_DATA_TYPE_nxv4bf16 = 175, // n x 4 x bf16 + CS_DATA_TYPE_nxv8bf16 = 176, // n x 8 x bf16 + CS_DATA_TYPE_nxv16bf16 = 177, // n x 16 x bf16 + CS_DATA_TYPE_nxv32bf16 = 178, // n x 32 x bf16 + + CS_DATA_TYPE_nxv1f32 = 179, // n x 1 x f32 + CS_DATA_TYPE_nxv2f32 = 180, // n x 2 x f32 + CS_DATA_TYPE_nxv4f32 = 181, // n x 4 x f32 + CS_DATA_TYPE_nxv8f32 = 182, // n x 8 x f32 + CS_DATA_TYPE_nxv16f32 = 183, // n x 16 x f32 + + CS_DATA_TYPE_nxv1f64 = 184, // n x 1 x f64 + CS_DATA_TYPE_nxv2f64 = 185, // n x 2 x f64 + CS_DATA_TYPE_nxv4f64 = 186, // n x 4 x f64 + CS_DATA_TYPE_nxv8f64 = 187, // n x 8 x f64 + + CS_DATA_TYPE_FIRST_FP_SCALABLE_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv1f16, + CS_DATA_TYPE_LAST_FP_SCALABLE_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv8f64, + + CS_DATA_TYPE_FIRST_SCALABLE_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv1i1, + CS_DATA_TYPE_LAST_SCALABLE_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv8f64, + + CS_DATA_TYPE_FIRST_VECTOR_VALUETYPE = CS_DATA_TYPE_v1i1, + CS_DATA_TYPE_LAST_VECTOR_VALUETYPE = CS_DATA_TYPE_nxv8f64, + + CS_DATA_TYPE_x86mmx = 188, // This is an X86 MMX value + + CS_DATA_TYPE_Glue = 189, // This glues nodes together during pre-RA sched + + CS_DATA_TYPE_isVoid = 190, // This has no value + + CS_DATA_TYPE_Untyped = 191, // This value takes a register, but has + // unspecified type. The register class + // will be determined by the opcode. + + CS_DATA_TYPE_funcref = 192, // WebAssembly's funcref type + CS_DATA_TYPE_externref = 193, // WebAssembly's externref type + CS_DATA_TYPE_x86amx = 194, // This is an X86 AMX value + CS_DATA_TYPE_i64x8 = 195, // 8 Consecutive GPRs (AArch64) + + CS_DATA_TYPE_FIRST_VALUETYPE = + 1, // This is always the beginning of the list. + CS_DATA_TYPE_LAST_VALUETYPE = + CS_DATA_TYPE_i64x8, // This always remains at the end of the list. + CS_DATA_TYPE_VALUETYPE_SIZE = CS_DATA_TYPE_LAST_VALUETYPE + 1, + + // This is the current maximum for LAST_VALUETYPE. + // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors + // This value must be a multiple of 32. + CS_DATA_TYPE_MAX_ALLOWED_VALUETYPE = 224, + + // A value of type llvm::TokenTy + CS_DATA_TYPE_token = 248, + + // This is MDNode or MDString. + CS_DATA_TYPE_Metadata = 249, + + // An int value the size of the pointer of the current + // target to any address space. This must only be used internal to + // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. + CS_DATA_TYPE_iPTRAny = 250, + + // A vector with any length and element size. This is used + // for intrinsics that have overloadings based on vector types. + // This is only for tblgen's consumption! + CS_DATA_TYPE_vAny = 251, + + // Any floating-point or vector floating-point value. This is used + // for intrinsics that have overloadings based on floating-point types. + // This is only for tblgen's consumption! + CS_DATA_TYPE_fAny = 252, + + // An integer or vector integer value of any bit width. This is + // used for intrinsics that have overloadings based on integer bit widths. + // This is only for tblgen's consumption! + CS_DATA_TYPE_iAny = 253, + + // An int value the size of the pointer of the current + // target. This should only be used internal to tblgen! + CS_DATA_TYPE_iPTR = 254, + + // Last element in enum. + CS_DATA_TYPE_LAST = 255 +} cs_data_type; + +/// Return true if this is a valid simple valuetype. +inline bool isValid(cs_data_type SimpleTy) +{ + return (SimpleTy >= CS_DATA_TYPE_FIRST_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_VALUETYPE); +} + +/// Return true if this is a FP or a vector FP type. +inline bool isFloatingPoint(cs_data_type SimpleTy) +{ + return ((SimpleTy >= CS_DATA_TYPE_FIRST_FP_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_FP_VALUETYPE) || + (SimpleTy >= CS_DATA_TYPE_FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_FP_FIXEDLEN_VECTOR_VALUETYPE) || + (SimpleTy >= CS_DATA_TYPE_FIRST_FP_SCALABLE_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_FP_SCALABLE_VECTOR_VALUETYPE)); +} + +/// Return true if this is an integer or a vector integer type. +inline bool isInteger(cs_data_type SimpleTy) +{ + return ((SimpleTy >= CS_DATA_TYPE_FIRST_INTEGER_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_INTEGER_VALUETYPE) || + (SimpleTy >= CS_DATA_TYPE_FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE) || + (SimpleTy >= CS_DATA_TYPE_FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE)); +} + +/// Return true if this is an integer, not including vectors. +inline bool isScalarInteger(cs_data_type SimpleTy) +{ + return (SimpleTy >= CS_DATA_TYPE_FIRST_INTEGER_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_INTEGER_VALUETYPE); +} + +/// Return true if this is a vector value type. +inline bool isVector(cs_data_type SimpleTy) +{ + return (SimpleTy >= CS_DATA_TYPE_FIRST_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_VECTOR_VALUETYPE); +} + +/// Return true if this is a vector value type where the +/// runtime length is machine dependent +inline bool isScalableVector(cs_data_type SimpleTy) +{ + return (SimpleTy >= CS_DATA_TYPE_FIRST_SCALABLE_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_SCALABLE_VECTOR_VALUETYPE); +} + +inline bool isFixedLengthVector(cs_data_type SimpleTy) +{ + return (SimpleTy >= CS_DATA_TYPE_FIRST_FIXEDLEN_VECTOR_VALUETYPE && + SimpleTy <= CS_DATA_TYPE_LAST_FIXEDLEN_VECTOR_VALUETYPE); +} + +/// Return true if this is a 16-bit vector type. +inline bool is16BitVector(cs_data_type SimpleTy) +{ + return (SimpleTy == CS_DATA_TYPE_v2i8 || SimpleTy == CS_DATA_TYPE_v1i16 || + SimpleTy == CS_DATA_TYPE_v16i1 || SimpleTy == CS_DATA_TYPE_v1f16); +} + +/// Return true if this is a 32-bit vector type. +inline bool is32BitVector(cs_data_type SimpleTy) +{ + return (SimpleTy == CS_DATA_TYPE_v32i1 || SimpleTy == CS_DATA_TYPE_v4i8 || + SimpleTy == CS_DATA_TYPE_v2i16 || SimpleTy == CS_DATA_TYPE_v1i32 || + SimpleTy == CS_DATA_TYPE_v2f16 || SimpleTy == CS_DATA_TYPE_v2bf16 || + SimpleTy == CS_DATA_TYPE_v1f32); +} + +/// Return true if this is a 64-bit vector type. +inline bool is64BitVector(cs_data_type SimpleTy) +{ + return (SimpleTy == CS_DATA_TYPE_v64i1 || SimpleTy == CS_DATA_TYPE_v8i8 || + SimpleTy == CS_DATA_TYPE_v4i16 || SimpleTy == CS_DATA_TYPE_v2i32 || + SimpleTy == CS_DATA_TYPE_v1i64 || SimpleTy == CS_DATA_TYPE_v4f16 || + SimpleTy == CS_DATA_TYPE_v4bf16 || SimpleTy == CS_DATA_TYPE_v2f32 || + SimpleTy == CS_DATA_TYPE_v1f64); +} + +/// Return true if this is a 128-bit vector type. +inline bool is128BitVector(cs_data_type SimpleTy) +{ + return (SimpleTy == CS_DATA_TYPE_v128i1 || SimpleTy == CS_DATA_TYPE_v16i8 || + SimpleTy == CS_DATA_TYPE_v8i16 || SimpleTy == CS_DATA_TYPE_v4i32 || + SimpleTy == CS_DATA_TYPE_v2i64 || SimpleTy == CS_DATA_TYPE_v1i128 || + SimpleTy == CS_DATA_TYPE_v8f16 || SimpleTy == CS_DATA_TYPE_v8bf16 || + SimpleTy == CS_DATA_TYPE_v4f32 || SimpleTy == CS_DATA_TYPE_v2f64); +} + +/// Return true if this is a 256-bit vector type. +inline bool is256BitVector(cs_data_type SimpleTy) +{ + return (SimpleTy == CS_DATA_TYPE_v16f16 || + SimpleTy == CS_DATA_TYPE_v16bf16 || + SimpleTy == CS_DATA_TYPE_v8f32 || SimpleTy == CS_DATA_TYPE_v4f64 || + SimpleTy == CS_DATA_TYPE_v32i8 || SimpleTy == CS_DATA_TYPE_v16i16 || + SimpleTy == CS_DATA_TYPE_v8i32 || SimpleTy == CS_DATA_TYPE_v4i64 || + SimpleTy == CS_DATA_TYPE_v256i1 || + SimpleTy == CS_DATA_TYPE_v128i2 || SimpleTy == CS_DATA_TYPE_v64i4); +} + +/// Return true if this is a 512-bit vector type. +inline bool is512BitVector(cs_data_type SimpleTy) +{ + return ( + SimpleTy == CS_DATA_TYPE_v32f16 || SimpleTy == CS_DATA_TYPE_v32bf16 || + SimpleTy == CS_DATA_TYPE_v16f32 || SimpleTy == CS_DATA_TYPE_v8f64 || + SimpleTy == CS_DATA_TYPE_v512i1 || SimpleTy == CS_DATA_TYPE_v256i2 || + SimpleTy == CS_DATA_TYPE_v128i4 || SimpleTy == CS_DATA_TYPE_v64i8 || + SimpleTy == CS_DATA_TYPE_v32i16 || SimpleTy == CS_DATA_TYPE_v16i32 || + SimpleTy == CS_DATA_TYPE_v8i64); +} + +/// Return true if this is a 1024-bit vector type. +inline bool is1024BitVector(cs_data_type SimpleTy) +{ + return ( + SimpleTy == CS_DATA_TYPE_v1024i1 || SimpleTy == CS_DATA_TYPE_v128i8 || + SimpleTy == CS_DATA_TYPE_v64i16 || SimpleTy == CS_DATA_TYPE_v32i32 || + SimpleTy == CS_DATA_TYPE_v16i64 || SimpleTy == CS_DATA_TYPE_v64f16 || + SimpleTy == CS_DATA_TYPE_v32f32 || SimpleTy == CS_DATA_TYPE_v16f64 || + SimpleTy == CS_DATA_TYPE_v64bf16); +} + +/// Return true if this is a 2048-bit vector type. +inline bool is2048BitVector(cs_data_type SimpleTy) +{ + return ( + SimpleTy == CS_DATA_TYPE_v256i8 || SimpleTy == CS_DATA_TYPE_v128i16 || + SimpleTy == CS_DATA_TYPE_v64i32 || SimpleTy == CS_DATA_TYPE_v32i64 || + SimpleTy == CS_DATA_TYPE_v128f16 || SimpleTy == CS_DATA_TYPE_v64f32 || + SimpleTy == CS_DATA_TYPE_v32f64 || SimpleTy == CS_DATA_TYPE_v128bf16 || + SimpleTy == CS_DATA_TYPE_v2048i1); +} + +inline cs_data_type getVectorElementType(cs_data_type SimpleTy) +{ + switch (SimpleTy) { + default: + assert(0 && "Not a vector MVT!"); + case CS_DATA_TYPE_v1i1: + case CS_DATA_TYPE_v2i1: + case CS_DATA_TYPE_v4i1: + case CS_DATA_TYPE_v8i1: + case CS_DATA_TYPE_v16i1: + case CS_DATA_TYPE_v32i1: + case CS_DATA_TYPE_v64i1: + case CS_DATA_TYPE_v128i1: + case CS_DATA_TYPE_v256i1: + case CS_DATA_TYPE_v512i1: + case CS_DATA_TYPE_v1024i1: + case CS_DATA_TYPE_v2048i1: + case CS_DATA_TYPE_nxv1i1: + case CS_DATA_TYPE_nxv2i1: + case CS_DATA_TYPE_nxv4i1: + case CS_DATA_TYPE_nxv8i1: + case CS_DATA_TYPE_nxv16i1: + case CS_DATA_TYPE_nxv32i1: + case CS_DATA_TYPE_nxv64i1: + return CS_DATA_TYPE_i1; + case CS_DATA_TYPE_v128i2: + case CS_DATA_TYPE_v256i2: + return CS_DATA_TYPE_i2; + case CS_DATA_TYPE_v64i4: + case CS_DATA_TYPE_v128i4: + return CS_DATA_TYPE_i4; + case CS_DATA_TYPE_v1i8: + case CS_DATA_TYPE_v2i8: + case CS_DATA_TYPE_v4i8: + case CS_DATA_TYPE_v8i8: + case CS_DATA_TYPE_v16i8: + case CS_DATA_TYPE_v32i8: + case CS_DATA_TYPE_v64i8: + case CS_DATA_TYPE_v128i8: + case CS_DATA_TYPE_v256i8: + case CS_DATA_TYPE_v512i8: + case CS_DATA_TYPE_v1024i8: + case CS_DATA_TYPE_nxv1i8: + case CS_DATA_TYPE_nxv2i8: + case CS_DATA_TYPE_nxv4i8: + case CS_DATA_TYPE_nxv8i8: + case CS_DATA_TYPE_nxv16i8: + case CS_DATA_TYPE_nxv32i8: + case CS_DATA_TYPE_nxv64i8: + return CS_DATA_TYPE_i8; + case CS_DATA_TYPE_v1i16: + case CS_DATA_TYPE_v2i16: + case CS_DATA_TYPE_v3i16: + case CS_DATA_TYPE_v4i16: + case CS_DATA_TYPE_v8i16: + case CS_DATA_TYPE_v16i16: + case CS_DATA_TYPE_v32i16: + case CS_DATA_TYPE_v64i16: + case CS_DATA_TYPE_v128i16: + case CS_DATA_TYPE_v256i16: + case CS_DATA_TYPE_v512i16: + case CS_DATA_TYPE_nxv1i16: + case CS_DATA_TYPE_nxv2i16: + case CS_DATA_TYPE_nxv4i16: + case CS_DATA_TYPE_nxv8i16: + case CS_DATA_TYPE_nxv16i16: + case CS_DATA_TYPE_nxv32i16: + return CS_DATA_TYPE_i16; + case CS_DATA_TYPE_v1i32: + case CS_DATA_TYPE_v2i32: + case CS_DATA_TYPE_v3i32: + case CS_DATA_TYPE_v4i32: + case CS_DATA_TYPE_v5i32: + case CS_DATA_TYPE_v6i32: + case CS_DATA_TYPE_v7i32: + case CS_DATA_TYPE_v8i32: + case CS_DATA_TYPE_v9i32: + case CS_DATA_TYPE_v10i32: + case CS_DATA_TYPE_v11i32: + case CS_DATA_TYPE_v12i32: + case CS_DATA_TYPE_v16i32: + case CS_DATA_TYPE_v32i32: + case CS_DATA_TYPE_v64i32: + case CS_DATA_TYPE_v128i32: + case CS_DATA_TYPE_v256i32: + case CS_DATA_TYPE_v512i32: + case CS_DATA_TYPE_v1024i32: + case CS_DATA_TYPE_v2048i32: + case CS_DATA_TYPE_nxv1i32: + case CS_DATA_TYPE_nxv2i32: + case CS_DATA_TYPE_nxv4i32: + case CS_DATA_TYPE_nxv8i32: + case CS_DATA_TYPE_nxv16i32: + case CS_DATA_TYPE_nxv32i32: + return CS_DATA_TYPE_i32; + case CS_DATA_TYPE_v1i64: + case CS_DATA_TYPE_v2i64: + case CS_DATA_TYPE_v3i64: + case CS_DATA_TYPE_v4i64: + case CS_DATA_TYPE_v8i64: + case CS_DATA_TYPE_v16i64: + case CS_DATA_TYPE_v32i64: + case CS_DATA_TYPE_v64i64: + case CS_DATA_TYPE_v128i64: + case CS_DATA_TYPE_v256i64: + case CS_DATA_TYPE_nxv1i64: + case CS_DATA_TYPE_nxv2i64: + case CS_DATA_TYPE_nxv4i64: + case CS_DATA_TYPE_nxv8i64: + case CS_DATA_TYPE_nxv16i64: + case CS_DATA_TYPE_nxv32i64: + return CS_DATA_TYPE_i64; + case CS_DATA_TYPE_v1i128: + return CS_DATA_TYPE_i128; + case CS_DATA_TYPE_v1f16: + case CS_DATA_TYPE_v2f16: + case CS_DATA_TYPE_v3f16: + case CS_DATA_TYPE_v4f16: + case CS_DATA_TYPE_v8f16: + case CS_DATA_TYPE_v16f16: + case CS_DATA_TYPE_v32f16: + case CS_DATA_TYPE_v64f16: + case CS_DATA_TYPE_v128f16: + case CS_DATA_TYPE_v256f16: + case CS_DATA_TYPE_v512f16: + case CS_DATA_TYPE_nxv1f16: + case CS_DATA_TYPE_nxv2f16: + case CS_DATA_TYPE_nxv4f16: + case CS_DATA_TYPE_nxv8f16: + case CS_DATA_TYPE_nxv16f16: + case CS_DATA_TYPE_nxv32f16: + return CS_DATA_TYPE_f16; + case CS_DATA_TYPE_v2bf16: + case CS_DATA_TYPE_v3bf16: + case CS_DATA_TYPE_v4bf16: + case CS_DATA_TYPE_v8bf16: + case CS_DATA_TYPE_v16bf16: + case CS_DATA_TYPE_v32bf16: + case CS_DATA_TYPE_v64bf16: + case CS_DATA_TYPE_v128bf16: + case CS_DATA_TYPE_nxv1bf16: + case CS_DATA_TYPE_nxv2bf16: + case CS_DATA_TYPE_nxv4bf16: + case CS_DATA_TYPE_nxv8bf16: + case CS_DATA_TYPE_nxv16bf16: + case CS_DATA_TYPE_nxv32bf16: + return CS_DATA_TYPE_bf16; + case CS_DATA_TYPE_v1f32: + case CS_DATA_TYPE_v2f32: + case CS_DATA_TYPE_v3f32: + case CS_DATA_TYPE_v4f32: + case CS_DATA_TYPE_v5f32: + case CS_DATA_TYPE_v6f32: + case CS_DATA_TYPE_v7f32: + case CS_DATA_TYPE_v8f32: + case CS_DATA_TYPE_v9f32: + case CS_DATA_TYPE_v10f32: + case CS_DATA_TYPE_v11f32: + case CS_DATA_TYPE_v12f32: + case CS_DATA_TYPE_v16f32: + case CS_DATA_TYPE_v32f32: + case CS_DATA_TYPE_v64f32: + case CS_DATA_TYPE_v128f32: + case CS_DATA_TYPE_v256f32: + case CS_DATA_TYPE_v512f32: + case CS_DATA_TYPE_v1024f32: + case CS_DATA_TYPE_v2048f32: + case CS_DATA_TYPE_nxv1f32: + case CS_DATA_TYPE_nxv2f32: + case CS_DATA_TYPE_nxv4f32: + case CS_DATA_TYPE_nxv8f32: + case CS_DATA_TYPE_nxv16f32: + return CS_DATA_TYPE_f32; + case CS_DATA_TYPE_v1f64: + case CS_DATA_TYPE_v2f64: + case CS_DATA_TYPE_v3f64: + case CS_DATA_TYPE_v4f64: + case CS_DATA_TYPE_v8f64: + case CS_DATA_TYPE_v16f64: + case CS_DATA_TYPE_v32f64: + case CS_DATA_TYPE_v64f64: + case CS_DATA_TYPE_v128f64: + case CS_DATA_TYPE_v256f64: + case CS_DATA_TYPE_nxv1f64: + case CS_DATA_TYPE_nxv2f64: + case CS_DATA_TYPE_nxv4f64: + case CS_DATA_TYPE_nxv8f64: + return CS_DATA_TYPE_f64; + } +} + +/// Given a vector type, return the minimum number of elements it contains. +inline unsigned getVectorMinNumElements(cs_data_type SimpleTy) +{ + switch (SimpleTy) { + default: + assert(0 && "Not a vector MVT!"); + case CS_DATA_TYPE_v2048i1: + case CS_DATA_TYPE_v2048i32: + case CS_DATA_TYPE_v2048f32: + return 2048; + case CS_DATA_TYPE_v1024i1: + case CS_DATA_TYPE_v1024i8: + case CS_DATA_TYPE_v1024i32: + case CS_DATA_TYPE_v1024f32: + return 1024; + case CS_DATA_TYPE_v512i1: + case CS_DATA_TYPE_v512i8: + case CS_DATA_TYPE_v512i16: + case CS_DATA_TYPE_v512i32: + case CS_DATA_TYPE_v512f16: + case CS_DATA_TYPE_v512f32: + return 512; + case CS_DATA_TYPE_v256i1: + case CS_DATA_TYPE_v256i2: + case CS_DATA_TYPE_v256i8: + case CS_DATA_TYPE_v256i16: + case CS_DATA_TYPE_v256f16: + case CS_DATA_TYPE_v256i32: + case CS_DATA_TYPE_v256i64: + case CS_DATA_TYPE_v256f32: + case CS_DATA_TYPE_v256f64: + return 256; + case CS_DATA_TYPE_v128i1: + case CS_DATA_TYPE_v128i2: + case CS_DATA_TYPE_v128i4: + case CS_DATA_TYPE_v128i8: + case CS_DATA_TYPE_v128i16: + case CS_DATA_TYPE_v128i32: + case CS_DATA_TYPE_v128i64: + case CS_DATA_TYPE_v128f16: + case CS_DATA_TYPE_v128bf16: + case CS_DATA_TYPE_v128f32: + case CS_DATA_TYPE_v128f64: + return 128; + case CS_DATA_TYPE_v64i1: + case CS_DATA_TYPE_v64i4: + case CS_DATA_TYPE_v64i8: + case CS_DATA_TYPE_v64i16: + case CS_DATA_TYPE_v64i32: + case CS_DATA_TYPE_v64i64: + case CS_DATA_TYPE_v64f16: + case CS_DATA_TYPE_v64bf16: + case CS_DATA_TYPE_v64f32: + case CS_DATA_TYPE_v64f64: + case CS_DATA_TYPE_nxv64i1: + case CS_DATA_TYPE_nxv64i8: + return 64; + case CS_DATA_TYPE_v32i1: + case CS_DATA_TYPE_v32i8: + case CS_DATA_TYPE_v32i16: + case CS_DATA_TYPE_v32i32: + case CS_DATA_TYPE_v32i64: + case CS_DATA_TYPE_v32f16: + case CS_DATA_TYPE_v32bf16: + case CS_DATA_TYPE_v32f32: + case CS_DATA_TYPE_v32f64: + case CS_DATA_TYPE_nxv32i1: + case CS_DATA_TYPE_nxv32i8: + case CS_DATA_TYPE_nxv32i16: + case CS_DATA_TYPE_nxv32i32: + case CS_DATA_TYPE_nxv32i64: + case CS_DATA_TYPE_nxv32f16: + case CS_DATA_TYPE_nxv32bf16: + return 32; + case CS_DATA_TYPE_v16i1: + case CS_DATA_TYPE_v16i8: + case CS_DATA_TYPE_v16i16: + case CS_DATA_TYPE_v16i32: + case CS_DATA_TYPE_v16i64: + case CS_DATA_TYPE_v16f16: + case CS_DATA_TYPE_v16bf16: + case CS_DATA_TYPE_v16f32: + case CS_DATA_TYPE_v16f64: + case CS_DATA_TYPE_nxv16i1: + case CS_DATA_TYPE_nxv16i8: + case CS_DATA_TYPE_nxv16i16: + case CS_DATA_TYPE_nxv16i32: + case CS_DATA_TYPE_nxv16i64: + case CS_DATA_TYPE_nxv16f16: + case CS_DATA_TYPE_nxv16bf16: + case CS_DATA_TYPE_nxv16f32: + return 16; + case CS_DATA_TYPE_v12i32: + case CS_DATA_TYPE_v12f32: + return 12; + case CS_DATA_TYPE_v11i32: + case CS_DATA_TYPE_v11f32: + return 11; + case CS_DATA_TYPE_v10i32: + case CS_DATA_TYPE_v10f32: + return 10; + case CS_DATA_TYPE_v9i32: + case CS_DATA_TYPE_v9f32: + return 9; + case CS_DATA_TYPE_v8i1: + case CS_DATA_TYPE_v8i8: + case CS_DATA_TYPE_v8i16: + case CS_DATA_TYPE_v8i32: + case CS_DATA_TYPE_v8i64: + case CS_DATA_TYPE_v8f16: + case CS_DATA_TYPE_v8bf16: + case CS_DATA_TYPE_v8f32: + case CS_DATA_TYPE_v8f64: + case CS_DATA_TYPE_nxv8i1: + case CS_DATA_TYPE_nxv8i8: + case CS_DATA_TYPE_nxv8i16: + case CS_DATA_TYPE_nxv8i32: + case CS_DATA_TYPE_nxv8i64: + case CS_DATA_TYPE_nxv8f16: + case CS_DATA_TYPE_nxv8bf16: + case CS_DATA_TYPE_nxv8f32: + case CS_DATA_TYPE_nxv8f64: + return 8; + case CS_DATA_TYPE_v7i32: + case CS_DATA_TYPE_v7f32: + return 7; + case CS_DATA_TYPE_v6i32: + case CS_DATA_TYPE_v6f32: + return 6; + case CS_DATA_TYPE_v5i32: + case CS_DATA_TYPE_v5f32: + return 5; + case CS_DATA_TYPE_v4i1: + case CS_DATA_TYPE_v4i8: + case CS_DATA_TYPE_v4i16: + case CS_DATA_TYPE_v4i32: + case CS_DATA_TYPE_v4i64: + case CS_DATA_TYPE_v4f16: + case CS_DATA_TYPE_v4bf16: + case CS_DATA_TYPE_v4f32: + case CS_DATA_TYPE_v4f64: + case CS_DATA_TYPE_nxv4i1: + case CS_DATA_TYPE_nxv4i8: + case CS_DATA_TYPE_nxv4i16: + case CS_DATA_TYPE_nxv4i32: + case CS_DATA_TYPE_nxv4i64: + case CS_DATA_TYPE_nxv4f16: + case CS_DATA_TYPE_nxv4bf16: + case CS_DATA_TYPE_nxv4f32: + case CS_DATA_TYPE_nxv4f64: + return 4; + case CS_DATA_TYPE_v3i16: + case CS_DATA_TYPE_v3i32: + case CS_DATA_TYPE_v3i64: + case CS_DATA_TYPE_v3f16: + case CS_DATA_TYPE_v3bf16: + case CS_DATA_TYPE_v3f32: + case CS_DATA_TYPE_v3f64: + return 3; + case CS_DATA_TYPE_v2i1: + case CS_DATA_TYPE_v2i8: + case CS_DATA_TYPE_v2i16: + case CS_DATA_TYPE_v2i32: + case CS_DATA_TYPE_v2i64: + case CS_DATA_TYPE_v2f16: + case CS_DATA_TYPE_v2bf16: + case CS_DATA_TYPE_v2f32: + case CS_DATA_TYPE_v2f64: + case CS_DATA_TYPE_nxv2i1: + case CS_DATA_TYPE_nxv2i8: + case CS_DATA_TYPE_nxv2i16: + case CS_DATA_TYPE_nxv2i32: + case CS_DATA_TYPE_nxv2i64: + case CS_DATA_TYPE_nxv2f16: + case CS_DATA_TYPE_nxv2bf16: + case CS_DATA_TYPE_nxv2f32: + case CS_DATA_TYPE_nxv2f64: + return 2; + case CS_DATA_TYPE_v1i1: + case CS_DATA_TYPE_v1i8: + case CS_DATA_TYPE_v1i16: + case CS_DATA_TYPE_v1i32: + case CS_DATA_TYPE_v1i64: + case CS_DATA_TYPE_v1i128: + case CS_DATA_TYPE_v1f16: + case CS_DATA_TYPE_v1f32: + case CS_DATA_TYPE_v1f64: + case CS_DATA_TYPE_nxv1i1: + case CS_DATA_TYPE_nxv1i8: + case CS_DATA_TYPE_nxv1i16: + case CS_DATA_TYPE_nxv1i32: + case CS_DATA_TYPE_nxv1i64: + case CS_DATA_TYPE_nxv1f16: + case CS_DATA_TYPE_nxv1bf16: + case CS_DATA_TYPE_nxv1f32: + case CS_DATA_TYPE_nxv1f64: + return 1; + } +} + +#endif // CS_SIMPLE_TYPES_H diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index d765d3f37..e02d6b052 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -210,6 +210,7 @@ typedef enum cs_opt_type { CS_OPT_SKIPDATA_SETUP, ///< Setup user-defined function for SKIPDATA option CS_OPT_MNEMONIC, ///< Customize instruction mnemonic CS_OPT_UNSIGNED, ///< print immediate operands in unsigned form + CS_OPT_NO_BRANCH_OFFSET, ///< ARM, prints branch immediates without offset. } cs_opt_type; /// Runtime option value (associated with option type above) @@ -229,8 +230,8 @@ typedef enum cs_op_type { CS_OP_INVALID = 0, ///< uninitialized/invalid operand. CS_OP_REG, ///< Register operand. CS_OP_IMM, ///< Immediate operand. - CS_OP_MEM, ///< Memory operand. CS_OP_FP, ///< Floating-Point operand. + CS_OP_MEM = 0x80, ///< Memory operand. Can be ORed with another operand type. } cs_op_type; /// Common instruction operand access types - to be consistent across all architectures. @@ -324,21 +325,27 @@ typedef struct cs_opt_skipdata { #include "sh.h" #include "tricore.h" +#define MAX_IMPL_W_REGS 20 +#define MAX_IMPL_R_REGS 20 +#define MAX_NUM_GROUPS 8 + /// NOTE: All information in cs_detail is only available when CS_OPT_DETAIL = CS_OPT_ON /// Initialized as memset(., 0, offsetof(cs_detail, ARCH)+sizeof(cs_ARCH)) /// by ARCH_getInstruction in arch/ARCH/ARCHDisassembler.c /// if cs_detail changes, in particular if a field is added after the union, /// then update arch/ARCH/ARCHDisassembler.c accordingly typedef struct cs_detail { - uint16_t regs_read[16]; ///< list of implicit registers read by this insn + uint16_t regs_read[MAX_IMPL_R_REGS]; ///< list of implicit registers read by this insn uint8_t regs_read_count; ///< number of implicit registers read by this insn - uint16_t regs_write[20]; ///< list of implicit registers modified by this insn + uint16_t regs_write[MAX_IMPL_W_REGS]; ///< list of implicit registers modified by this insn uint8_t regs_write_count; ///< number of implicit registers modified by this insn - uint8_t groups[8]; ///< list of group this instruction belong to + uint8_t groups[MAX_NUM_GROUPS]; ///< list of group this instruction belong to uint8_t groups_count; ///< number of groups this insn belongs to + bool writeback; ///< Instruction has writeback operands. + /// Architecture-specific instruction info union { cs_x86 x86; ///< X86 architecture, including 16-bit, 32-bit & 64-bit mode diff --git a/utils.c b/utils.c index efb9da767..e7de64604 100644 --- a/utils.c +++ b/utils.c @@ -11,62 +11,6 @@ #include "utils.h" -// create a cache for fast id lookup -static unsigned short *make_id2insn(const insn_map *insns, unsigned int size) -{ - // NOTE: assume that the max id is always put at the end of insns array - unsigned short max_id = insns[size - 1].id; - unsigned short i; - - unsigned short *cache = (unsigned short *)cs_mem_calloc(max_id + 1, sizeof(*cache)); - - for (i = 1; i < size; i++) - cache[insns[i].id] = i; - - return cache; -} - -// look for @id in @insns, given its size in @max. first time call will update @cache. -// return 0 if not found -unsigned short insn_find(const insn_map *insns, unsigned int max, unsigned int id, unsigned short **cache) -{ - if (id > insns[max - 1].id) - return 0; - - if (*cache == NULL) - *cache = make_id2insn(insns, max); - - return (*cache)[id]; -} - -int name2id(const name_map* map, int max, const char *name) -{ - int i; - - for (i = 0; i < max; i++) { - if (!strcmp(map[i].name, name)) { - return map[i].id; - } - } - - // nothing match - return -1; -} - -const char *id2name(const name_map* map, int max, const unsigned int id) -{ - int i; - - for (i = 0; i < max; i++) { - if (map[i].id == id) { - return map[i].name; - } - } - - // nothing match - return NULL; -} - // count number of positive members in a list. // NOTE: list must be guaranteed to end in 0 unsigned int count_positive(const uint16_t *list) @@ -167,3 +111,30 @@ unsigned int binsearch_IndexTypeEncoding(const struct IndexType *index, size_t s // not found return -1; } + +/// Reads 4 bytes in the endian order specified in MI->cs->mode. +uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes) +{ + assert(MI && Bytes); + uint32_t Insn; + if (MODE_IS_BIG_ENDIAN(MI->csh->mode)) + Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | + ((uint32_t)Bytes[0] << 24); + else + Insn = ((uint32_t)Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | + (Bytes[0] << 0); + return Insn; +} + +/// Reads 2 bytes in the endian order specified in MI->cs->mode. +uint16_t readBytes16(MCInst *MI, const uint8_t *Bytes) +{ + assert(MI && Bytes); + uint16_t Insn; + if (MODE_IS_BIG_ENDIAN(MI->csh->mode)) + Insn = (Bytes[0] << 8) | Bytes[1]; + else + Insn = (Bytes[1] << 8) | Bytes[0]; + + return Insn; +} diff --git a/utils.h b/utils.h index 520e0b419..5076e00b1 100644 --- a/utils.h +++ b/utils.h @@ -11,41 +11,11 @@ #include "include/capstone/capstone.h" #endif #include "cs_priv.h" +#include "Mapping.h" // threshold number, so above this number will be printed in hexa mode #define HEX_THRESHOLD 9 -// map instruction to its characteristics -typedef struct insn_map { - unsigned short id; - unsigned short mapid; -#ifndef CAPSTONE_DIET - uint16_t regs_use[12]; // list of implicit registers used by this instruction - uint16_t regs_mod[20]; // list of implicit registers modified by this instruction - unsigned char groups[8]; // list of group this instruction belong to - bool branch; // branch instruction? - bool indirect_branch; // indirect branch instruction? -#endif -} insn_map; - -// look for @id in @m, given its size in @max. first time call will update @cache. -// return 0 if not found -unsigned short insn_find(const insn_map *m, unsigned int max, unsigned int id, unsigned short **cache); - -// map id to string -typedef struct name_map { - unsigned int id; - const char *name; -} name_map; - -// map a name to its ID -// return 0 if not found -int name2id(const name_map* map, int max, const char *name); - -// map ID to a name -// return NULL if not found -const char *id2name(const name_map* map, int max, const unsigned int id); - // count number of positive members in a list. // NOTE: list must be guaranteed to end in 0 unsigned int count_positive(const uint16_t *list); @@ -77,5 +47,8 @@ struct IndexType { // return -1 if not found, or index if found unsigned int binsearch_IndexTypeEncoding(const struct IndexType *index, size_t size, uint16_t encoding); +uint16_t readBytes16(MCInst *MI, const uint8_t *Bytes); +uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes); + #endif