diff --git a/.clang-format b/.clang-format index e9361226e3..8d5b1fead1 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,120 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# For more information, see: +# +# Documentation/process/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true BraceWrapping: - AfterClass: true + AfterClass: false AfterControlStatement: false - AfterFunction: true + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom -UseTab: Always \ No newline at end of file +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 8 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 8 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 8 +UseTab: Always diff --git a/CMakeLists.txt b/CMakeLists.txt index b5c759b948..7a986a08ab 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 @@ -545,11 +548,11 @@ if (CAPSTONE_TRICORE_SUPPORT) ) set(HEADERS_TRICORE arch/TriCore/TriCoreDisassembler.h + arch/TriCore/TriCoreLinkage.h arch/TriCore/TriCoreGenAsmWriter.inc 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 c41be14882..1e876ce291 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,74 @@ 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 2e5df74264..e3ecf4299a 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; @@ -30,10 +31,14 @@ typedef struct MCOperand MCOperand; /// This is a simple discriminated union. struct MCOperand { enum { - kInvalid = 0, ///< Uninitialized. - kRegister, ///< Register operand. - kImmediate, ///< Immediate operand. - kFPImmediate, ///< Floating-point immediate operand. + kInvalid = 0, ///< Uninitialized. + 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,9 @@ 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 +154,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 9bb264a437..f0984bdfd5 100644 --- a/MCInstrDesc.c +++ b/MCInstrDesc.c @@ -16,3 +16,26 @@ 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 f97555308f..001059c78a 100644 --- a/MCInstrDesc.h +++ b/MCInstrDesc.h @@ -158,4 +158,10 @@ 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/Makefile b/Makefile index e288e43050..f84d43c1f0 100644 --- a/Makefile +++ b/Makefile @@ -326,11 +326,10 @@ endif LIBOBJ = -LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o +LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o $(OBJDIR)/MCInst.o $(OBJDIR)/Mapping.o LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_RISCV) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ) $(LIBOBJ_SH) LIBOBJ += $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX) $(LIBOBJ_WASM) $(LIBOBJ_BPF) LIBOBJ += $(LIBOBJ_TRICORE) -LIBOBJ += $(OBJDIR)/MCInst.o ifeq ($(PKG_EXTRA),) diff --git a/Mapping.c b/Mapping.c new file mode 100644 index 0000000000..f887293cbe --- /dev/null +++ b/Mapping.c @@ -0,0 +1,254 @@ +/* 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); +DEFINE_get_detail_op(tricore, TriCore); diff --git a/Mapping.h b/Mapping.h new file mode 100644 index 0000000000..87e4d085d3 --- /dev/null +++ b/Mapping.h @@ -0,0 +1,174 @@ +/* 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, (const map_insn_ops *)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, (const map_insn_ops *)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); +DECL_get_detail_op(tricore, TriCore); + +/// 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); +DEFINE_inc_detail_op_count(tricore, TriCore); +DEFINE_dec_detail_op_count(tricore, TriCore); + +/// 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); +DEFINE_get_arch_detail(tricore, TriCore); + +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/arch/TriCore/TriCoreDisassembler.c b/arch/TriCore/TriCoreDisassembler.c index dc7e05f57a..408f516c59 100644 --- a/arch/TriCore/TriCoreDisassembler.c +++ b/arch/TriCore/TriCoreDisassembler.c @@ -27,31 +27,8 @@ #include "../../MathExtras.h" #include "TriCoreDisassembler.h" - -static bool readInstruction16(const uint8_t *code, size_t code_len, - uint16_t *insn) -{ - if (code_len < 2) - // insufficient data - return false; - - // Encoded as a little-endian 16-bit word in the stream. - *insn = (code[0] << 0) | (code[1] << 8); - return true; -} - -static bool readInstruction32(const uint8_t *code, size_t code_len, - uint32_t *insn) -{ - if (code_len < 4) - // insufficient data - return false; - - // Encoded as a little-endian 32-bit word in the stream. - *insn = (code[0] << 0) | (code[1] << 8) | (code[2] << 16) | - (code[3] << 24); - return true; -} +#include "TriCoreMapping.h" +#include "TriCoreLinkage.h" static unsigned getReg(MCRegisterInfo *MRI, unsigned RC, unsigned RegNo) { @@ -1485,14 +1462,12 @@ static inline bool tryGetInstruction16(const uint8_t *code, size_t code_len, uint64_t address, void *info, const uint8_t *decoderTable16) { - uint16_t insn16; - DecodeStatus Result; - if (!readInstruction16(code, code_len, &insn16)) { + if (code_len < 2) { return false; } - // Calling the auto-generated decoder function. - Result = decodeInstruction_2(decoderTable16, MI, insn16, address, info, - 0); + uint16_t insn16 = readBytes16(MI, code); + DecodeStatus Result = decodeInstruction_2(decoderTable16, MI, insn16, + address, info, 0); if (Result != MCDisassembler_Fail) { *size = 2; return true; @@ -1505,14 +1480,12 @@ static inline bool tryGetInstruction32(const uint8_t *code, size_t code_len, uint64_t address, void *info, const uint8_t *decoderTable32) { - uint32_t insn32; - DecodeStatus Result; - if (!readInstruction32(code, code_len, &insn32)) { + if (code_len < 4) { return false; } - // Calling the auto-generated decoder function. - Result = decodeInstruction_4(decoderTable32, MI, insn32, address, info, - 0); + uint32_t insn32 = readBytes32(MI, code); + DecodeStatus Result = decodeInstruction_4(decoderTable32, MI, insn32, + address, info, 0); if (Result != MCDisassembler_Fail) { *size = 4; return true; @@ -1520,9 +1493,9 @@ static inline bool tryGetInstruction32(const uint8_t *code, size_t code_len, return false; } -bool TriCore_getInstruction(csh ud, const uint8_t *code, size_t code_len, - MCInst *MI, uint16_t *size, uint64_t address, - void *info) +static bool getInstruction(csh ud, const uint8_t *code, size_t code_len, + MCInst *MI, uint16_t *size, uint64_t address, + void *info) { if (!ud) { return false; @@ -1569,7 +1542,19 @@ bool TriCore_getInstruction(csh ud, const uint8_t *code, size_t code_len, DecoderTable32); } -void TriCore_init(MCRegisterInfo *MRI) +bool TriCore_LLVM_getInstruction(csh handle, const uint8_t *Bytes, + size_t ByteLen, MCInst *MI, uint16_t *Size, + uint64_t Address, void *Info) +{ + bool Result = + getInstruction(handle, Bytes, ByteLen, MI, Size, Address, Info); + if (Result) { + TriCore_set_instr_map_data(MI); + } + return Result; +} + +void TriCore_init_mri(MCRegisterInfo *MRI) { /* InitMCRegisterInfo(TriCoreRegDesc, 45, RA, PC, diff --git a/arch/TriCore/TriCoreDisassembler.h b/arch/TriCore/TriCoreDisassembler.h index de4f53bf9a..0809d951db 100644 --- a/arch/TriCore/TriCoreDisassembler.h +++ b/arch/TriCore/TriCoreDisassembler.h @@ -12,12 +12,7 @@ #include "../../MCRegisterInfo.h" #include "../../MCInst.h" -void TriCore_init(MCRegisterInfo *MRI); - -bool TriCore_getInstruction(csh ud, const uint8_t *code, size_t code_len, - MCInst *instr, uint16_t *size, uint64_t address, - void *info); - +void TriCore_init_mri(MCRegisterInfo *MRI); bool TriCore_getFeatureBits(unsigned int mode, unsigned int feature); #endif diff --git a/arch/TriCore/TriCoreInstPrinter.c b/arch/TriCore/TriCoreInstPrinter.c index d927c02c7c..f5c8fdc1c7 100644 --- a/arch/TriCore/TriCoreInstPrinter.c +++ b/arch/TriCore/TriCoreInstPrinter.c @@ -26,8 +26,8 @@ #include "../../MathExtras.h" #include "../../SStream.h" #include "../../utils.h" -#include "TriCoreInstPrinter.h" #include "TriCoreMapping.h" +#include "TriCoreLinkage.h" static const char *getRegisterName(unsigned RegNo); @@ -35,14 +35,6 @@ static void printInstruction(MCInst *, uint64_t, SStream *); static void printOperand(MCInst *MI, int OpNum, SStream *O); -void TriCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci) -{ - /* - if (((cs_struct *)ud)->detail != CS_OPT_ON) - return; - */ -} - #define GET_INSTRINFO_ENUM #include "TriCoreGenInstrInfo.inc" @@ -51,39 +43,47 @@ void TriCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci) #include "TriCoreGenRegisterInfo.inc" -static inline void fill_mem(cs_tricore *tc, uint8_t base, int32_t disp); +static bool fill_mem(MCInst *MI, unsigned int reg, int32_t disp); -static bool fixup_op_mem(MCInst *pInst, unsigned int reg, int32_t disp); +static inline void set_mem(cs_tricore_op *op, uint8_t base, int32_t disp) +{ + op->type |= TRICORE_OP_MEM; + op->mem.base = base; + op->mem.disp = disp; +} -static inline void fill_tricore_register(MCInst *MI, uint32_t reg) +static inline void fill_reg(MCInst *MI, uint32_t reg) { - if (!(MI->csh->detail == CS_OPT_ON && MI->flat_insn->detail)) + if (!detail_is_set(MI)) return; - cs_tricore *tricore = &MI->flat_insn->detail->tricore; - tricore->operands[tricore->op_count].type = TRICORE_OP_REG; - tricore->operands[tricore->op_count].reg = reg; - tricore->op_count++; + cs_tricore_op *op = TriCore_get_detail_op(MI, 0); + op->type = TRICORE_OP_REG; + op->reg = reg; + TriCore_inc_op_count(MI); } -static inline void fill_tricore_imm(MCInst *MI, int32_t imm) +static inline void fill_imm(MCInst *MI, int32_t imm) { - if (!(MI->csh->detail == CS_OPT_ON && MI->flat_insn->detail)) - return; - cs_tricore *tricore = &MI->flat_insn->detail->tricore; - if (tricore->op_count >= 1 && - tricore->operands[tricore->op_count - 1].type == TRICORE_OP_REG && - fixup_op_mem(MI, tricore->operands[tricore->op_count - 1].reg, - imm)) { + if (!detail_is_set(MI)) return; + cs_tricore *tricore = TriCore_get_detail(MI); + if (tricore->op_count >= 1) { + cs_tricore_op *op = TriCore_get_detail_op(MI, -1); + if (op->type == TRICORE_OP_REG && fill_mem(MI, op->reg, imm)) + return; } - tricore->operands[tricore->op_count].type = TRICORE_OP_IMM; - tricore->operands[tricore->op_count].imm = imm; + + cs_tricore_op *op = TriCore_get_detail_op(MI, 0); + op->type = TRICORE_OP_IMM; + op->imm = imm; tricore->op_count++; } -static bool fixup_op_mem(MCInst *pInst, unsigned int reg, int32_t disp) +static bool fill_mem(MCInst *MI, unsigned int reg, int32_t disp) { - switch (TriCore_map_insn_id(pInst->csh, pInst->Opcode)) { + if (!detail_is_set(MI)) + return false; + switch (MI->flat_insn->id) { case TRICORE_INS_LDMST: case TRICORE_INS_LDLCX: case TRICORE_INS_LD_A: @@ -116,7 +116,7 @@ static bool fixup_op_mem(MCInst *pInst, unsigned int reg, int32_t disp) case TRICORE_INS_SWAPMSK_W: case TRICORE_INS_LEA: case TRICORE_INS_LHA: { - switch (MCInst_getOpcode(pInst)) { + switch (MCInst_getOpcode(MI)) { case TRICORE_LDMST_abs: case TRICORE_LDLCX_abs: case TRICORE_LD_A_abs: @@ -144,50 +144,29 @@ static bool fixup_op_mem(MCInst *pInst, unsigned int reg, int32_t disp) return false; } } - cs_tricore *tc = &pInst->flat_insn->detail->tricore; - fill_mem(tc, reg, disp); + cs_tricore_op *op = TriCore_get_detail_op(MI, -1); + op->type = 0; + set_mem(op, reg, disp); return true; } } return false; } -static inline void fill_mem(cs_tricore *tc, uint8_t base, int32_t disp) -{ - cs_tricore_op *op = &tc->operands[tc->op_count - 1]; - op->type = TRICORE_OP_MEM; - op->mem.base = base; - op->mem.disp = disp; -} - static void printOperand(MCInst *MI, int OpNum, SStream *O) { - MCOperand *Op; if (OpNum >= MI->size) return; - Op = MCInst_getOperand(MI, OpNum); - + MCOperand *Op = MCInst_getOperand(MI, OpNum); if (MCOperand_isReg(Op)) { unsigned reg = MCOperand_getReg(Op); SStream_concat(O, "%%%s", getRegisterName(reg)); - fill_tricore_register(MI, reg); + fill_reg(MI, reg); } else if (MCOperand_isImm(Op)) { int64_t Imm = MCOperand_getImm(Op); - - if (Imm >= 0) { - if (Imm > HEX_THRESHOLD) - SStream_concat(O, "0x%" PRIx64, Imm); - else - SStream_concat(O, "%" PRIu64, Imm); - } else { - if (Imm < -HEX_THRESHOLD) - SStream_concat(O, "-0x%" PRIx64, -Imm); - else - SStream_concat(O, "-%" PRIu64, -Imm); - } - - fill_tricore_imm(MI, (int32_t)Imm); + printInt64(O, Imm); + fill_imm(MI, (int32_t)Imm); } } @@ -216,7 +195,7 @@ static void print_sign_ext(MCInst *MI, int OpNum, SStream *O, unsigned n) int32_t imm = (int32_t)MCOperand_getImm(MO); imm = sign_ext_n(imm, n); printInt32(O, imm); - fill_tricore_imm(MI, imm); + fill_imm(MI, imm); } else printOperand(MI, OpNum, O); } @@ -257,18 +236,8 @@ static void print_zero_ext(MCInst *MI, int OpNum, SStream *O, unsigned n) off4_fixup(MI, &imm); } - if (imm >= 0) { - if (imm > HEX_THRESHOLD) - SStream_concat(O, "0x%x", imm); - else - SStream_concat(O, "%u", imm); - } else { - if (imm < -HEX_THRESHOLD) - SStream_concat(O, "-0x%x", -imm); - else - SStream_concat(O, "-%u", -imm); - } - fill_tricore_imm(MI, imm); + printInt64(O, imm); + fill_imm(MI, imm); } else printOperand(MI, OpNum, O); } @@ -280,7 +249,7 @@ static void printOff18Imm(MCInst *MI, int OpNum, SStream *O) uint32_t imm = (uint32_t)MCOperand_getImm(MO); imm = ((imm & 0x3C000) << 14) | (imm & 0x3fff); SStream_concat(O, "0x%x", imm); - fill_tricore_imm(MI, (int32_t)imm); + fill_imm(MI, (int32_t)imm); } else printOperand(MI, OpNum, O); } @@ -311,7 +280,7 @@ static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O) } printUInt32(O, disp); - fill_tricore_imm(MI, disp); + fill_imm(MI, disp); } else printOperand(MI, OpNum, O); } @@ -356,7 +325,7 @@ static void printDisp15Imm(MCInst *MI, int OpNum, SStream *O) } printUInt32(O, disp); - fill_tricore_imm(MI, disp); + fill_imm(MI, disp); } else printOperand(MI, OpNum, O); } @@ -381,7 +350,7 @@ static void printDisp8Imm(MCInst *MI, int OpNum, SStream *O) } printUInt32(O, disp); - fill_tricore_imm(MI, disp); + fill_imm(MI, disp); } else printOperand(MI, OpNum, O); } @@ -426,7 +395,7 @@ static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O) } printUInt32(O, disp); - fill_tricore_imm(MI, disp); + fill_imm(MI, disp); } else printOperand(MI, OpNum, O); } @@ -467,7 +436,7 @@ static void printOExtImm_4(MCInst *MI, int OpNum, SStream *O) imm = 0b11111111111111111111111111100000 | (imm << 1); printInt32(O, imm); - fill_tricore_imm(MI, imm); + fill_imm(MI, imm); } else printOperand(MI, OpNum, O); } @@ -485,7 +454,7 @@ static void set_mem_access(MCInst *MI, unsigned int access) #include "TriCoreGenAsmWriter.inc" -const char *TriCore_getRegisterName(csh handle, unsigned int id) +const char *TriCore_LLVM_getRegisterName(unsigned int id) { #ifndef CAPSTONE_DIET return getRegisterName(id); @@ -494,9 +463,10 @@ const char *TriCore_getRegisterName(csh handle, unsigned int id) #endif } -void TriCore_printInst(MCInst *MI, SStream *O, void *Info) +void TriCore_LLVM_printInst(MCInst *MI, uint64_t Address, SStream *O) { - printInstruction(MI, MI->address, O); + printInstruction(MI, Address, O); + TriCore_set_access(MI); } -#endif +#endif // CAPSTONE_HAS_TRICORE diff --git a/arch/TriCore/TriCoreInstPrinter.h b/arch/TriCore/TriCoreInstPrinter.h deleted file mode 100644 index 2313baa1b0..0000000000 --- a/arch/TriCore/TriCoreInstPrinter.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Capstone Disassembly Engine */ -/* By Nguyen Anh Quynh , 2013-2014 */ - -#ifndef CS_TRICOREINSTPRINTER_H -#define CS_TRICOREINSTPRINTER_H - -#include "../../MCInst.h" -#include "../../MCRegisterInfo.h" -#include "../../SStream.h" -#include "./TriCoreMapping.h" - -const char *TriCore_getRegisterName(csh handle, unsigned int id); - -void TriCore_printInst(MCInst *MI, SStream *O, void *Info); - -void TriCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci); - -#endif diff --git a/arch/TriCore/TriCoreLinkage.h b/arch/TriCore/TriCoreLinkage.h new file mode 100644 index 0000000000..cfee58f77f --- /dev/null +++ b/arch/TriCore/TriCoreLinkage.h @@ -0,0 +1,21 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh , 2013-2019 */ + +#ifndef CS_TRICORE_LINKAGE_H +#define CS_TRICORE_LINKAGE_H + +// Function defintions to call static LLVM functions. + +#include "../../MCDisassembler.h" +#include "../../MCInst.h" +#include "../../MCRegisterInfo.h" +#include "../../SStream.h" +#include "capstone/capstone.h" + +bool TriCore_LLVM_getInstruction(csh handle, const uint8_t *Bytes, + size_t ByteLen, MCInst *MI, uint16_t *Size, + uint64_t Address, void *Info); +const char *TriCore_LLVM_getRegisterName(unsigned RegNo); +void TriCore_LLVM_printInst(MCInst *MI, uint64_t Address, SStream *O); + +#endif // CS_TRICORE_LINKAGE_H diff --git a/arch/TriCore/TriCoreMapping.c b/arch/TriCore/TriCoreMapping.c index d9e998e55e..63cd5150d4 100644 --- a/arch/TriCore/TriCoreMapping.c +++ b/arch/TriCore/TriCoreMapping.c @@ -5,10 +5,13 @@ #include // debug #include +#include #include "../../utils.h" +#include "../../cs_simple_types.h" #include "TriCoreMapping.h" +#include "TriCoreLinkage.h" #define GET_INSTRINFO_ENUM @@ -30,52 +33,41 @@ static insn_map insns[] = { #include "TriCoreGenCSMappingInsn.inc" }; -unsigned int TriCore_map_insn_id(cs_struct *h, unsigned int id) -{ - unsigned short i = - insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); - if (i != 0) { - return insns[i].mapid; - } - return 0; -} - -// given internal insn id, return public instruction info void TriCore_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) { - unsigned short i; + // Not used. Information is set after disassembly. +} - i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); - if (i != 0) { - insn->id = insns[i].mapid; +#ifndef CAPSTONE_DIET +static tricore_reg flag_regs[] = { TRICORE_REG_PSW }; +#endif // CAPSTONE_DIET - if (h->detail) { +static inline void check_updates_flags(MCInst *MI) +{ #ifndef CAPSTONE_DIET - memcpy(insn->detail->regs_read, insns[i].regs_use, - sizeof(insns[i].regs_use)); - insn->detail->regs_read_count = - (uint8_t)count_positive(insns[i].regs_use); - - memcpy(insn->detail->regs_write, insns[i].regs_mod, - sizeof(insns[i].regs_mod)); - insn->detail->regs_write_count = - (uint8_t)count_positive(insns[i].regs_mod); - - memcpy(insn->detail->groups, insns[i].groups, - sizeof(insns[i].groups)); - insn->detail->groups_count = - (uint8_t)count_positive8(insns[i].groups); - - if (insns[i].branch || insns[i].indirect_branch) { - // this insn also belongs to JUMP group. add JUMP group - insn->detail - ->groups[insn->detail->groups_count] = - TRICORE_GRP_JUMP; - insn->detail->groups_count++; + if (!MI->flat_insn->detail) + return; + cs_detail *detail = MI->flat_insn->detail; + for (int i = 0; i < detail->regs_write_count; ++i) { + if (detail->regs_write[i] == 0) + return; + for (int j = 0; j < ARR_SIZE(flag_regs); ++j) { + if (detail->regs_write[i] == flag_regs[j]) { + detail->tricore.update_flags = true; + return; } -#endif } } +#endif // CAPSTONE_DIET +} + +void TriCore_set_instr_map_data(MCInst *MI) +{ + map_cs_id(MI, insns, ARR_SIZE(insns)); + map_implicit_reads(MI, insns); + map_implicit_writes(MI, insns); + check_updates_flags(MI); + map_groups(MI, insns); } #ifndef CAPSTONE_DIET @@ -130,4 +122,120 @@ const char *TriCore_group_name(csh handle, unsigned int id) #endif } +#ifndef CAPSTONE_DIET +/// A LLVM<->CS Mapping entry of an operand. +typedef struct insn_op { + 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[10]; ///< List of op types. Terminated by CS_DATA_TYPE_LAST +} insn_op; + +///< Operands of an instruction. +typedef struct { + insn_op ops[16]; ///< NULL terminated array of operands. +} insn_ops; + +const insn_ops insn_operands[] = { +#include "TriCoreGenCSMappingInsnOp.inc" +}; #endif + +void TriCore_set_access(MCInst *MI) +{ +#ifndef CAPSTONE_DIET + if (!(MI->csh->detail == CS_OPT_ON && MI->flat_insn->detail)) + return; + + assert(MI->Opcode < ARR_SIZE(insn_operands)); + + cs_detail *detail = MI->flat_insn->detail; + cs_tricore *tc = &(detail->tricore); + for (int i = 0; i < tc->op_count; ++i) { + cs_ac_type ac = map_get_op_access(MI, i); + cs_tricore_op *op = &tc->operands[i]; + op->access = ac; + cs_op_type op_type = map_get_op_type(MI, i); + if (op_type != CS_OP_REG) { + continue; + } + if (ac & CS_AC_READ) { + detail->regs_read[detail->regs_read_count++] = op->reg; + } + if (ac & CS_AC_WRITE) { + detail->regs_write[detail->regs_write_count++] = + op->reg; + } + } +#endif +} + +void TriCore_reg_access(const cs_insn *insn, cs_regs regs_read, + uint8_t *regs_read_count, cs_regs regs_write, + uint8_t *regs_write_count) +{ +#ifndef CAPSTONE_DIET + uint8_t read_count, write_count; + cs_detail *detail = insn->detail; + read_count = detail->regs_read_count; + write_count = detail->regs_write_count; + + // implicit registers + memcpy(regs_read, detail->regs_read, + read_count * sizeof(detail->regs_read[0])); + memcpy(regs_write, detail->regs_write, + write_count * sizeof(detail->regs_write[0])); + + // explicit registers + cs_tricore *tc = &detail->tricore; + for (uint8_t i = 0; i < tc->op_count; i++) { + cs_tricore_op *op = &(tc->operands[i]); + switch ((int)op->type) { + case TRICORE_OP_REG: + if ((op->access & CS_AC_READ) && + !arr_exist(regs_read, read_count, op->reg)) { + regs_read[read_count] = (uint16_t)op->reg; + read_count++; + } + if ((op->access & CS_AC_WRITE) && + !arr_exist(regs_write, write_count, op->reg)) { + regs_write[write_count] = (uint16_t)op->reg; + write_count++; + } + break; + case TRICORE_OP_MEM: + // registers appeared in memory references always being read + if ((op->mem.base != ARM_REG_INVALID) && + !arr_exist(regs_read, read_count, op->mem.base)) { + regs_read[read_count] = (uint16_t)op->mem.base; + read_count++; + } + default: + break; + } + } + + *regs_read_count = read_count; + *regs_write_count = write_count; +#endif +} + +bool TriCore_getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen, + MCInst *MI, uint16_t *Size, uint64_t Address, + void *Info) +{ + return TriCore_LLVM_getInstruction(handle, Bytes, ByteLen, MI, Size, + Address, Info); +} + +void TriCore_printInst(MCInst *MI, SStream *O, void *Info) +{ + TriCore_LLVM_printInst(MI, MI->address, O); +} + +const char *TriCore_getRegisterName(csh handle, unsigned int RegNo) +{ + return TriCore_LLVM_getRegisterName(RegNo); +} + +#endif // CAPSTONE_HAS_TRICORE diff --git a/arch/TriCore/TriCoreMapping.h b/arch/TriCore/TriCoreMapping.h index 57ef507d27..2b0f94d3eb 100644 --- a/arch/TriCore/TriCoreMapping.h +++ b/arch/TriCore/TriCoreMapping.h @@ -6,8 +6,6 @@ #include -unsigned int TriCore_map_insn_id(cs_struct *h, unsigned int id); - // given internal insn id, return public instruction info void TriCore_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id); @@ -15,7 +13,20 @@ const char *TriCore_insn_name(csh handle, unsigned int id); const char *TriCore_group_name(csh handle, unsigned int id); -cs_err TRICORE_global_init(cs_struct *ud); -cs_err TRICORE_option(cs_struct *handle, cs_opt_type type, size_t value); +void TriCore_reg_access(const cs_insn *insn, cs_regs regs_read, + uint8_t *regs_read_count, cs_regs regs_write, + uint8_t *regs_write_count); + +void TriCore_set_access(MCInst *MI); + +void TriCore_set_instr_map_data(MCInst *MI); + +bool TriCore_getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen, + MCInst *MI, uint16_t *Size, uint64_t Address, + void *Info); + +void TriCore_printInst(MCInst *MI, SStream *O, void *Info); + +const char *TriCore_getRegisterName(csh handle, unsigned int RegNo); #endif diff --git a/arch/TriCore/TriCoreModule.c b/arch/TriCore/TriCoreModule.c index a0aca3b4b3..c97d36b2ec 100644 --- a/arch/TriCore/TriCoreModule.c +++ b/arch/TriCore/TriCoreModule.c @@ -4,9 +4,9 @@ #ifdef CAPSTONE_HAS_TRICORE #include "../../utils.h" -#include "TriCoreDisassembler.h" -#include "TriCoreInstPrinter.h" #include "TriCoreMapping.h" +#include "TriCoreModule.h" +#include "TriCoreDisassembler.h" cs_err TRICORE_global_init(cs_struct *ud) { @@ -14,18 +14,22 @@ cs_err TRICORE_global_init(cs_struct *ud) mri = cs_mem_malloc(sizeof(*mri)); - TriCore_init(mri); + TriCore_init_mri(mri); ud->printer = TriCore_printInst; ud->printer_info = mri; ud->getinsn_info = mri; ud->disasm = TriCore_getInstruction; - ud->post_printer = TriCore_post_printer; + ud->post_printer = NULL; ud->reg_name = TriCore_getRegisterName; ud->insn_id = TriCore_get_insn_id; ud->insn_name = TriCore_insn_name; ud->group_name = TriCore_group_name; +#ifndef CAPSTONE_DIET + ud->reg_access = TriCore_reg_access; +#endif + return CS_ERR_OK; } diff --git a/cs_simple_types.h b/cs_simple_types.h new file mode 100644 index 0000000000..1dc9576265 --- /dev/null +++ b/cs_simple_types.h @@ -0,0 +1,886 @@ +/* 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/cstool/cstool_tricore.c b/cstool/cstool_tricore.c index d5ac10dc6c..28446e7a98 100644 --- a/cstool/cstool_tricore.c +++ b/cstool/cstool_tricore.c @@ -34,39 +34,51 @@ void print_insn_detail_tricore(csh handle, cs_insn *ins) op->imm); break; case TRICORE_OP_MEM: - printf("\t\toperands[%u].type: MEM\n", i); - if (op->mem.base != TRICORE_REG_INVALID) - printf("\t\t\toperands[%u].mem.base: REG = %s\n", - i, cs_reg_name(handle, op->mem.base)); - if (op->mem.disp != 0) - printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, - op->mem.disp); + printf("\t\toperands[%u].type: MEM\n" + "\t\t\t.mem.base: REG = %s\n" + "\t\t\t.mem.disp: 0x%x\n", + i, cs_reg_name(handle, op->mem.base), + op->mem.disp); break; } - // Print out all registers accessed by this instruction (either implicit or - // explicit) - if (!cs_regs_access(handle, ins, regs_read, ®s_read_count, - regs_write, ®s_write_count)) { - if (regs_read_count) { - printf("\tRegisters read:"); - for (i = 0; i < regs_read_count; i++) { - printf(" %s", - cs_reg_name(handle, - regs_read[i])); - } - printf("\n"); + switch (op->access) { + default: + break; + case CS_AC_READ: + printf("\t\t\t.access: READ\n"); + break; + case CS_AC_WRITE: + printf("\t\t\t.access: WRITE\n"); + break; + case CS_AC_READ | CS_AC_WRITE: + printf("\t\t\t.access: READ | WRITE\n"); + break; + } + } + // Print out all registers accessed by this instruction (either implicit or + // explicit) + if (!cs_regs_access(handle, ins, regs_read, ®s_read_count, + regs_write, ®s_write_count)) { + if (regs_read_count) { + printf("\tRegisters read:"); + for (i = 0; i < regs_read_count; i++) { + printf(" %s", + cs_reg_name(handle, regs_read[i])); } + printf("\n"); + } - if (regs_write_count) { - printf("\tRegisters modified:"); - for (i = 0; i < regs_write_count; i++) { - printf(" %s", - cs_reg_name(handle, - regs_write[i])); - } - printf("\n"); + if (regs_write_count) { + printf("\tRegisters modified:"); + for (i = 0; i < regs_write_count; i++) { + printf(" %s", + cs_reg_name(handle, regs_write[i])); } + printf("\n"); } } + + if (tricore->update_flags) + printf("\tUpdate-flags: True\n"); } diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index d765d3f375..d028fb574e 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -201,15 +201,16 @@ typedef struct cs_opt_mnem { /// Runtime option for the disassembled engine typedef enum cs_opt_type { - CS_OPT_INVALID = 0, ///< No option specified - CS_OPT_SYNTAX, ///< Assembly output syntax - CS_OPT_DETAIL, ///< Break down instruction structure into details - CS_OPT_MODE, ///< Change engine's mode at run-time - CS_OPT_MEM, ///< User-defined dynamic memory related functions + CS_OPT_INVALID = 0, ///< No option specified + CS_OPT_SYNTAX, ///< Assembly output syntax + CS_OPT_DETAIL, ///< Break down instruction structure into details + CS_OPT_MODE, ///< Change engine's mode at run-time + CS_OPT_MEM, ///< User-defined dynamic memory related functions CS_OPT_SKIPDATA, ///< Skip data when disassembling. Then engine is in SKIPDATA mode. 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_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) @@ -226,11 +227,12 @@ typedef enum cs_opt_value { /// Common instruction operand types - to be consistent across all architectures. 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_INVALID = 0, ///< uninitialized/invalid operand. + CS_OP_REG, ///< Register operand. + CS_OP_IMM, ///< Immediate 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 +326,29 @@ 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/include/capstone/tricore.h b/include/capstone/tricore.h index aa63d65993..cc64e899ca 100644 --- a/include/capstone/tricore.h +++ b/include/capstone/tricore.h @@ -18,40 +18,46 @@ extern "C" { #pragma warning(disable : 4201) #endif -//> Operand type for instruction's operands +/// Operand type for instruction's operands typedef enum tricore_op_type { - TRICORE_OP_INVALID = 0, // = CS_OP_INVALID (Uninitialized). - TRICORE_OP_REG, // = CS_OP_REG (Register operand). - TRICORE_OP_IMM, // = CS_OP_IMM (Immediate operand). - TRICORE_OP_MEM, // = CS_OP_MEM (Memory operand). + TRICORE_OP_INVALID = CS_OP_INVALID, ///< CS_OP_INVALID (Uninitialized). + TRICORE_OP_REG = CS_OP_REG, ///< CS_OP_REG (Register operand). + TRICORE_OP_IMM = CS_OP_IMM, ///< CS_OP_IMM (Immediate operand). + TRICORE_OP_MEM = CS_OPT_MEM, ///< CS_OP_MEM (Memory operand). } tricore_op_type; -// Instruction's operand referring to memory -// This is associated with TRICORE_OP_MEM operand type above +/// Instruction's operand referring to memory +/// This is associated with TRICORE_OP_MEM operand type above typedef struct tricore_op_mem { - uint8_t base; // base register - int32_t disp; // displacement/offset value + uint8_t base; ///< base register + int32_t disp; ///< displacement/offset value } tricore_op_mem; -// Instruction operand +/// Instruction operand typedef struct cs_tricore_op { - tricore_op_type type; // operand type + tricore_op_type type; ///< operand type union { - unsigned int reg; // register value for REG operand - int32_t imm; // immediate value for IMM operand - tricore_op_mem mem; // base/disp value for MEM operand + unsigned int reg; ///< register value for REG operand + int32_t imm; ///< immediate value for IMM operand + tricore_op_mem mem; ///< base/disp value for MEM operand }; + /// This field is combined of cs_ac_type. + /// NOTE: this field is irrelevant if engine is compiled in DIET mode. + uint8_t access; ///< How is this operand accessed? (READ, WRITE or READ|WRITE) } cs_tricore_op; -// Instruction structure +#define TRICORE_OP_COUNT 8 + +/// Instruction structure typedef struct cs_tricore { - // Number of operands of this instruction, - // or 0 when instruction has no operand. - uint8_t op_count; - cs_tricore_op operands[8]; // operands for this instruction. + uint8_t op_count; ///< number of operands of this instruction. + cs_tricore_op + operands[TRICORE_OP_COUNT]; ///< operands for this instruction. + /// TODO: Mark the modified flags register in td files and regenerate inc files + bool update_flags; ///< whether the flags register is updated. } cs_tricore; -//> TriCore registers +/// TriCore registers typedef enum tricore_reg { // generate content begin // clang-format off @@ -123,7 +129,7 @@ typedef enum tricore_reg { // generate content end } tricore_reg; -//> TriCore instruction +/// TriCore instruction typedef enum tricore_insn { TRICORE_INS_INVALID = 0, // generate content begin @@ -525,13 +531,13 @@ typedef enum tricore_insn { TRICORE_INS_ENDING, // <-- mark the end of the list of instructions } tricore_insn; -//> Group of TriCore instructions +/// Group of TriCore instructions typedef enum tricore_insn_group { TRICORE_GRP_INVALID, ///< = CS_GRP_INVALID - //> Generic groups - TRICORE_GRP_CALL, ///< = CS_GRP_CALL - TRICORE_GRP_JUMP, ///< = CS_GRP_JUMP - TRICORE_GRP_ENDING, ///< = mark the end of the list of groups + /// Generic groups + TRICORE_GRP_CALL, ///< = CS_GRP_CALL + TRICORE_GRP_JUMP, ///< = CS_GRP_JUMP + TRICORE_GRP_ENDING, ///< mark the end of the list of groups } tricore_insn_group; typedef enum tricore_feature_t { @@ -551,7 +557,7 @@ typedef enum tricore_feature_t { // clang-format on // generate content end - TRICORE_FEATURE_ENDING, // <-- mark the end of the list of features + TRICORE_FEATURE_ENDING, ///< mark the end of the list of features } tricore_feature; #ifdef __cplusplus diff --git a/suite/arm/test_arm_regression.c b/suite/arm/test_arm_regression.c index 5146251ea4..31a46c25af 100644 --- a/suite/arm/test_arm_regression.c +++ b/suite/arm/test_arm_regression.c @@ -35,7 +35,7 @@ static char *hex_string(unsigned char *str, size_t len) if (!hex_out) { goto Exit; } for (i = 0; i < len; ++i) { - snprintf(hex_out + (i*2), 2, "%02x", str[i]); + snprintf(hex_out + (i * 2), 3, "%02x", str[i]); } hex_out[len*2] = 0; // trailing null @@ -46,8 +46,6 @@ static char *hex_string(unsigned char *str, size_t len) static void snprint_insn_detail(char * buf, size_t * cur, size_t * left, cs_insn *ins) { - size_t used = 0; - #define _this_printf(...) \ { \ size_t used = 0; \ @@ -84,10 +82,10 @@ static void snprint_insn_detail(char * buf, size_t * cur, size_t * left, cs_insn break; case ARM_OP_MEM: _this_printf("\t\toperands[%u].type: MEM\n", i); - if (op->mem.base != X86_REG_INVALID) + if (op->mem.base != ARM_REG_INVALID) _this_printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base)); - if (op->mem.index != X86_REG_INVALID) + if (op->mem.index != ARM_REG_INVALID) _this_printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index)); if (op->mem.scale != 1) @@ -286,9 +284,7 @@ static void test_valids() } }}; - struct valid_instructions * valid = NULL; - - uint64_t address = 0x1000; + struct valid_instructions *valid = NULL; cs_insn *insn; int i; int j; @@ -323,8 +319,6 @@ static void test_valids() char tmp_buf[2048]; size_t left = 2048; size_t cur = 0; - size_t used = 0; - int success = 0; char * hex_str = NULL; struct valid_code * valid_code = NULL; diff --git a/suite/cstest/src/capstone_test.c b/suite/cstest/src/capstone_test.c index 779ab251d6..984355585f 100644 --- a/suite/cstest/src/capstone_test.c +++ b/suite/cstest/src/capstone_test.c @@ -9,8 +9,8 @@ char *(*function)(csh *, cs_mode, cs_insn*) = NULL; void test_single_MC(csh *handle, int mc_mode, char *line) { char **list_part, **list_byte; - int size_part, size_byte, size_data, size_insn; - int i, count, count_noreg; + int size_part, size_byte; + int i, count; unsigned char *code; cs_insn *insn; char tmp[MAXMEM], tmp_mc[MAXMEM], origin[MAXMEM], tmp_noreg[MAXMEM]; @@ -72,7 +72,7 @@ void test_single_MC(csh *handle, int mc_mode, char *line) replace_negative(tmp, mc_mode); if (cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME) == CS_ERR_OK) { - count_noreg = cs_disasm(*handle, code, size_byte, offset, 0, &insn); + cs_disasm(*handle, code, size_byte, offset, 0, &insn); strcpy(tmp_noreg, insn[0].mnemonic); if (strlen(insn[0].op_str) > 0) { tmp_noreg[strlen(insn[0].mnemonic)] = ' '; @@ -192,8 +192,8 @@ int set_function(int arch) void test_single_issue(csh *handle, cs_mode mode, char *line, int detail) { - char **list_part, **list_byte, **list_part_cs_result, **list_part_issue_result; - int size_part, size_byte, size_part_cs_result, size_part_issue_result; + char **list_part, **list_byte, **list_part_issue_result; + int size_part, size_byte, size_part_issue_result; char *tmptmp; int i, count, j; unsigned char *code; @@ -246,7 +246,7 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail) } } } - + trim_str(cs_result); add_str(&cs_result, " ;"); // list_part_cs_result = split(cs_result, " ; ", &size_part_cs_result); @@ -255,8 +255,8 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail) for (i = 0; i < size_part_issue_result; ++i) { trim_str(list_part_issue_result[i]); - memset(tmptmp, MAXMEM, 0); - + memset(tmptmp, 0, MAXMEM); + tmptmp = (char *)malloc(sizeof(char)); tmptmp[0] = '\0'; add_str(&tmptmp, "%s", list_part_issue_result[i]); diff --git a/suite/cstest/src/helper.c b/suite/cstest/src/helper.c index 02365510ca..a70dca3d4f 100644 --- a/suite/cstest/src/helper.c +++ b/suite/cstest/src/helper.c @@ -108,7 +108,7 @@ void add_str(char **src, const char *format, ...) void replace_hex(char *src) { char *tmp, *result, *found, *origin, *orig_found; - int i, valid; + int valid; unsigned long long int value; char *tmp_tmp; @@ -155,7 +155,7 @@ void replace_hex(char *src) void replace_negative(char *src, int mode) { char *tmp, *result, *found, *origin, *orig_found; - int i, cnt, valid; + int cnt, valid; char *value, *tmp_tmp; unsigned short int tmp_short; unsigned int tmp_int; diff --git a/suite/cstest/src/main.c b/suite/cstest/src/main.c index 67802d7d0c..c8e458fb86 100644 --- a/suite/cstest/src/main.c +++ b/suite/cstest/src/main.c @@ -140,7 +140,7 @@ static int setup_MC(void **state) char **list_params; int size_params; int arch, mode; - int i, index, tmp_counter; + int i, tmp_counter; if (failed_setup) { fprintf(stderr, "[ ERROR ] --- Invalid file to setup\n"); @@ -241,8 +241,7 @@ static int setup_issue(void **state) char **list_params; int size_params; int arch, mode; - int i, index, result; - char *(*function)(csh *, cs_mode, cs_insn*); + int i, result; getDetail = 0; failed_setup = 0; @@ -369,11 +368,10 @@ static int teardown_issue(void **state) static void test_file(const char *filename) { - int size, i; - char **list_str; + int i; char *content, *tmp; struct CMUnitTest *tests; - int issue_num, number_of_tests; + int number_of_tests; printf("[+] TARGET: %s\n", filename); content = readfile(filename); diff --git a/tests/test_sh.c b/tests/test_sh.c index a578110523..439b1c2241 100644 --- a/tests/test_sh.c +++ b/tests/test_sh.c @@ -96,8 +96,8 @@ static void print_insn_detail(csh handle, cs_insn *insn) break; case SH_OP_IMM: - printf("\t\toperands[%u].type: IMMEDIATE = #%d\n", i, - op->imm); + printf("\t\toperands[%u].type: IMMEDIATE = #%lu\n", i, + op->imm); break; case SH_OP_MEM: @@ -138,6 +138,8 @@ static void print_insn_detail(csh handle, cs_insn *insn) printf("TBR base with displacement DISP %d\n", op->mem.disp); break; + case SH_OP_MEM_INVALID: + break; } break; } diff --git a/utils.c b/utils.c index efb9da7677..2bcbd1eec2 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 520e0b4197..5076e00b1b 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