From 45cfa7b0f78e28045541c065aad918d548452d58 Mon Sep 17 00:00:00 2001 From: billow Date: Fri, 7 Jun 2024 03:47:40 +0800 Subject: [PATCH] Xtensa: fix --- CMakeLists.txt | 2 + Mapping.h | 2 + arch/Xtensa/XtensaDisassembler.c | 32 ++++--- arch/Xtensa/XtensaDisassembler.h | 5 +- arch/Xtensa/XtensaGenCSFeatureEnum.inc | 14 --- arch/Xtensa/XtensaInstPrinter.c | 114 ++++++---------------- arch/Xtensa/XtensaInstPrinter.h | 29 +----- arch/Xtensa/XtensaMapping.c | 125 +++++++++++++++++++++++-- arch/Xtensa/XtensaMapping.h | 6 ++ arch/Xtensa/priv.h | 2 +- cstool/cstool.c | 6 +- cstool/cstool_xtensa.c | 1 - include/capstone/capstone.h | 2 + include/capstone/xtensa.h | 51 +++++++++- 14 files changed, 236 insertions(+), 155 deletions(-) delete mode 100644 arch/Xtensa/XtensaGenCSFeatureEnum.inc diff --git a/CMakeLists.txt b/CMakeLists.txt index 61d5835359..457539346f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") endif() +set(BUILD_RPATH_USE_ORIGIN true) + # Detect whether capstone is compiled as top-level or a subdirectory set(PROJECT_IS_TOP_LEVEL OFF) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) diff --git a/Mapping.h b/Mapping.h index 9b5de0afe0..22515565d0 100644 --- a/Mapping.h +++ b/Mapping.h @@ -152,6 +152,8 @@ DEFINE_inc_detail_op_count(alpha, Alpha); DEFINE_dec_detail_op_count(alpha, Alpha); DEFINE_inc_detail_op_count(hppa, HPPA); DEFINE_dec_detail_op_count(hppa, HPPA); +DEFINE_inc_detail_op_count(xtensa, Xtensa); +DEFINE_dec_detail_op_count(xtensa, Xtensa); /// Returns true if a memory operand is currently edited. static inline bool doing_mem(const MCInst *MI) diff --git a/arch/Xtensa/XtensaDisassembler.c b/arch/Xtensa/XtensaDisassembler.c index d8c15fb96f..5237dec026 100644 --- a/arch/Xtensa/XtensaDisassembler.c +++ b/arch/Xtensa/XtensaDisassembler.c @@ -235,7 +235,7 @@ static DecodeStatus decodeMem32Operand(MCInst *Inst, uint64_t Imm, /// Read three bytes from the ArrayRef and return 24 bit data static DecodeStatus readInstruction24(const uint8_t *Bytes, const unsigned BytesSize, uint64_t *Size, - uint32_t *Insn, bool IsLittleEndian) + uint32_t *Insn) { // We want to read exactly 3 Bytes of data. if (BytesSize < 3) { @@ -243,14 +243,7 @@ static DecodeStatus readInstruction24(const uint8_t *Bytes, return MCDisassembler_Fail; } - if (!IsLittleEndian) { - report_fatal_error( - "Big-endian mode currently is not supported!"); - return MCDisassembler_Fail; - } else { - *Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); - } - + *Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); *Size = 3; return MCDisassembler_Success; } @@ -262,18 +255,29 @@ DecodeToMCInst(decode_to_MCInst, field_from_inst, uint32_t); DecodeInstruction(decodeInstruction, field_from_inst, decode_to_MCInst, uint32_t); -DecodeStatus getInstruction(MCInst *MI, uint64_t *Size, const uint8_t *Bytes, - const unsigned BytesSize, uint64_t Address) +static DecodeStatus getInstruction(MCInst *MI, uint64_t *Size, + const uint8_t *Bytes, unsigned BytesSize, + uint64_t Address) { uint32_t Insn; DecodeStatus Result; - bool IsLittleEndian = MI->csh->mode & CS_MODE_BIG_ENDIAN; - Result = readInstruction24(Bytes, BytesSize, Size, &Insn, - IsLittleEndian); + Result = readInstruction24(Bytes, BytesSize, Size, &Insn); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; // LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n"); Result = decodeInstruction(DecoderTable24, MI, Insn, Address, NULL); return Result; } + +DecodeStatus Xtensa_LLVM_getInstruction(MCInst *MI, uint16_t *size16, + const uint8_t *Bytes, + unsigned BytesSize, uint64_t Address) +{ + uint64_t size64; + DecodeStatus status = + getInstruction(MI, &size64, Bytes, BytesSize, Address); + assert(size64 < 0xffff); + *size16 = size64; + return status == MCDisassembler_Success; +} diff --git a/arch/Xtensa/XtensaDisassembler.h b/arch/Xtensa/XtensaDisassembler.h index bf8da925e3..ae5b8a557d 100644 --- a/arch/Xtensa/XtensaDisassembler.h +++ b/arch/Xtensa/XtensaDisassembler.h @@ -3,7 +3,8 @@ #include "../../MCDisassembler.h" -DecodeStatus getInstruction(MCInst *MI, uint64_t *Size, const uint8_t *Bytes, - unsigned BytesSize, uint64_t Address); +DecodeStatus Xtensa_LLVM_getInstruction(MCInst *MI, uint16_t *Size, + const uint8_t *Bytes, + unsigned BytesSize, uint64_t Address); #endif diff --git a/arch/Xtensa/XtensaGenCSFeatureEnum.inc b/arch/Xtensa/XtensaGenCSFeatureEnum.inc deleted file mode 100644 index f9ac1b8381..0000000000 --- a/arch/Xtensa/XtensaGenCSFeatureEnum.inc +++ /dev/null @@ -1,14 +0,0 @@ -/* Capstone Disassembly Engine, https://www.capstone-engine.org */ -/* By Nguyen Anh Quynh , 2013-2022, */ -/* Rot127 2022-2024 */ -/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */ - -/* LLVM-commit: */ -/* LLVM-tag: */ - -/* Do not edit. */ - -/* Capstone's LLVM TableGen Backends: */ -/* https://github.com/capstone-engine/llvm-capstone */ - -Xtensa_FEATURE_HasDensity = 128, diff --git a/arch/Xtensa/XtensaInstPrinter.c b/arch/Xtensa/XtensaInstPrinter.c index 488a40ade0..a28a545717 100644 --- a/arch/Xtensa/XtensaInstPrinter.c +++ b/arch/Xtensa/XtensaInstPrinter.c @@ -42,7 +42,7 @@ static MnemonicBitsInfo getMnemonic(MCInst *MI, SStream *O); static const char *getRegisterName(unsigned RegNo); -void printOperand_(const MCOperand *MC, SStream *O) +static void printOperand_(const MCOperand *MC, SStream *O) { if (MCOperand_isReg(MC)) SStream_concat0(O, getRegisterName(MCOperand_getReg(MC))); @@ -54,17 +54,12 @@ void printOperand_(const MCOperand *MC, SStream *O) report_fatal_error("Invalid operand"); } -void printRegName(SStream *O, MCRegister Reg) -{ - SStream_concat0(O, getRegisterName(Reg)); -} - -void printOperand(MCInst *MI, int OpNum, SStream *O) +static void printOperand(MCInst *MI, int OpNum, SStream *O) { printOperand_(MCInst_getOperand(MI, (OpNum)), O); } -void printMemOperand(MCInst *MI, int OpNum, SStream *OS) +static inline void printMemOperand(MCInst *MI, int OpNum, SStream *OS) { SStream_concat0(OS, getRegisterName(MCOperand_getReg( MCInst_getOperand(MI, (OpNum))))); @@ -72,7 +67,7 @@ void printMemOperand(MCInst *MI, int OpNum, SStream *OS) printOperand(MI, OpNum + 1, OS); } -void printBranchTarget(MCInst *MI, int OpNum, SStream *OS) +static inline void printBranchTarget(MCInst *MI, int OpNum, SStream *OS) { MCOperand *MC = MCInst_getOperand(MI, (OpNum)); if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { @@ -82,12 +77,11 @@ void printBranchTarget(MCInst *MI, int OpNum, SStream *OS) SStream_concat0(OS, "+"); printInt64(OS, Val); - } - else + } else assert(0 && "Invalid operand"); } -void printJumpTarget(MCInst *MI, int OpNum, SStream *OS) +static inline void printJumpTarget(MCInst *MI, int OpNum, SStream *OS) { MCOperand *MC = MCInst_getOperand(MI, (OpNum)); if (MCOperand_isImm(MC)) { @@ -97,13 +91,12 @@ void printJumpTarget(MCInst *MI, int OpNum, SStream *OS) SStream_concat0(OS, "+"); printInt64(OS, Val); - } - else + } else assert(0 && "Invalid operand"); ; } -void printCallOperand(MCInst *MI, int OpNum, SStream *OS) +static inline void printCallOperand(MCInst *MI, int OpNum, SStream *OS) { MCOperand *MC = MCInst_getOperand(MI, (OpNum)); if (MCOperand_isImm(MC)) { @@ -113,12 +106,11 @@ void printCallOperand(MCInst *MI, int OpNum, SStream *OS) SStream_concat0(OS, "+"); printInt64(OS, Val); - } - else + } else assert(0 && "Invalid operand"); } -void printL32RTarget(MCInst *MI, int OpNum, SStream *O) +static inline void printL32RTarget(MCInst *MI, int OpNum, SStream *O) { MCOperand *MC = MCInst_getOperand(MI, (OpNum)); if (MCOperand_isImm(MC)) { @@ -130,12 +122,11 @@ void printL32RTarget(MCInst *MI, int OpNum, SStream *O) Value += ((InstrOff + 0x3) & 0x4) - InstrOff; SStream_concat0(O, ". "); printInt64(O, Value); - } - else + } else assert(0 && "Invalid operand"); } -void printImm8_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printImm8_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -147,29 +138,7 @@ void printImm8_AsmOperand(MCInst *MI, int OpNum, SStream *O) } } -void printImm8_sh8_AsmOperand(MCInst *MI, int OpNum, SStream *O) -{ - if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { - int64_t Value = - MCOperand_getImm(MCInst_getOperand(MI, (OpNum))); - - printInt64(O, Value); - } else - printOperand(MI, OpNum, O); -} - -void printImm12_AsmOperand(MCInst *MI, int OpNum, SStream *O) -{ - if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { - int64_t Value = - MCOperand_getImm(MCInst_getOperand(MI, (OpNum))); - - printInt64(O, Value); - } else - printOperand(MI, OpNum, O); -} - -void printImm12m_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printImm8_sh8_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -180,7 +149,7 @@ void printImm12m_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printUimm4_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printImm12m_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -191,7 +160,7 @@ void printUimm4_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printUimm5_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printUimm4_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -202,7 +171,7 @@ void printUimm5_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printShimm1_31_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printUimm5_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -213,7 +182,7 @@ void printShimm1_31_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printImm1_16_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printShimm1_31_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -224,7 +193,7 @@ void printImm1_16_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printOffset8m8_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printImm1_16_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -235,40 +204,7 @@ void printOffset8m8_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printOffset8m16_AsmOperand(MCInst *MI, int OpNum, SStream *O) -{ - if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { - int64_t Value = - MCOperand_getImm(MCInst_getOperand(MI, (OpNum))); - - printInt64(O, Value); - } else - printOperand(MI, OpNum, O); -} - -void printOffset8m32_AsmOperand(MCInst *MI, int OpNum, SStream *O) -{ - if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { - int64_t Value = - MCOperand_getImm(MCInst_getOperand(MI, (OpNum))); - - printInt64(O, Value); - } else - printOperand(MI, OpNum, O); -} - -void printOffset4m32_AsmOperand(MCInst *MI, int OpNum, SStream *O) -{ - if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { - int64_t Value = - MCOperand_getImm(MCInst_getOperand(MI, (OpNum))); - - printInt64(O, Value); - } else - printOperand(MI, OpNum, O); -} - -void printB4const_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printB4const_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -300,7 +236,7 @@ void printB4const_AsmOperand(MCInst *MI, int OpNum, SStream *O) printOperand(MI, OpNum, O); } -void printB4constu_AsmOperand(MCInst *MI, int OpNum, SStream *O) +static inline void printB4constu_AsmOperand(MCInst *MI, int OpNum, SStream *O) { if (MCOperand_isImm(MCInst_getOperand(MI, (OpNum)))) { int64_t Value = @@ -333,3 +269,13 @@ void printB4constu_AsmOperand(MCInst *MI, int OpNum, SStream *O) } #include "XtensaGenAsmWriter.inc" + +const char *Xtensa_LLVM_getRegisterName(unsigned RegNo) +{ + return getRegisterName(RegNo); +} + +void Xtensa_LLVM_printInstruction(MCInst *MI, uint64_t Address, SStream *O) +{ + printInstruction(MI, Address, O); +} diff --git a/arch/Xtensa/XtensaInstPrinter.h b/arch/Xtensa/XtensaInstPrinter.h index f7869a7a7a..29c1d0e7b3 100644 --- a/arch/Xtensa/XtensaInstPrinter.h +++ b/arch/Xtensa/XtensaInstPrinter.h @@ -39,32 +39,7 @@ #include "priv.h" -// Automatically generated by tblgen. -void printInstruction(MCInst *MI, uint64_t Address, SStream *O); -// Override MCInstPrinter. -void printRegName(SStream *O, MCRegister Reg); -// Print various types of operand. -void printOperand(MCInst *MI, int OpNum, SStream *O); -void printMemOperand(MCInst *MI, int OpNUm, SStream *O); -void printBranchTarget(MCInst *MI, int OpNum, SStream *O); -void printJumpTarget(MCInst *MI, int OpNum, SStream *O); -void printCallOperand(MCInst *MI, int OpNum, SStream *O); -void printL32RTarget(MCInst *MI, int OpNum, SStream *O); -void printImm8_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printImm8_sh8_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printImm12_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printImm12m_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printUimm4_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printUimm5_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printShimm1_31_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printImm1_16_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printOffset8m8_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printOffset8m16_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printOffset8m32_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printOffset4m32_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printB4const_AsmOperand(MCInst *MI, int OpNum, SStream *O); -void printB4constu_AsmOperand(MCInst *MI, int OpNum, SStream *O); -; -// end namespace llvm +const char *Xtensa_LLVM_getRegisterName(unsigned RegNo); +void Xtensa_LLVM_printInstruction(MCInst *MI, uint64_t Address, SStream *O); #endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H */ diff --git a/arch/Xtensa/XtensaMapping.c b/arch/Xtensa/XtensaMapping.c index ec74220273..6a17459121 100644 --- a/arch/Xtensa/XtensaMapping.c +++ b/arch/Xtensa/XtensaMapping.c @@ -1,50 +1,157 @@ +#include + #include "../../MCRegisterInfo.h" #include "../../MCInst.h" #include "../../SStream.h" +#include "../../Mapping.h" +#include "../../utils.h" +#include "../../cs_simple_types.h" #include "XtensaDisassembler.h" #include "XtensaInstPrinter.h" +#ifndef CAPSTONE_DIET + +#define GET_INSTRINFO_ENUM +#include "XtensaGenInstrInfo.inc" + +static const char *const insn_name_maps[] = { +#include "XtensaGenCSMappingInsnName.inc" +}; + +static const name_map group_name_maps[] = { +#include "XtensaGenCSFeatureName.inc" +}; + +const insn_map mapping_insns[] = { +#include "XtensaGenCSMappingInsn.inc" +}; + +//static const map_insn_ops insn_operands[] = { +//#include "XtensaGenCSMappingInsnOp.inc" +//}; + +#endif + void Xtensa_init_mri(MCRegisterInfo *mri) { } void Xtensa_printer(MCInst *MI, SStream *OS, void *info) { - printInstruction(MI, MI->address, OS); + Xtensa_LLVM_printInstruction(MI, MI->address, OS); +} + +static void set_instr_map_data(MCInst *MI) +{ +#ifndef CAPSTONE_DIET + map_cs_id(MI, mapping_insns, ARR_SIZE(mapping_insns)); + map_implicit_reads(MI, mapping_insns); + map_implicit_writes(MI, mapping_insns); + map_groups(MI, mapping_insns); +#endif } bool Xtensa_disasm(csh handle, const uint8_t *code, size_t code_len, MCInst *instr, uint16_t *size, uint64_t address, void *info) { - uint64_t size64; - DecodeStatus status = - getInstruction(instr, &size64, code, code_len, address); - assert(size64 < 0xffff); - *size = size64; - return status == MCDisassembler_Success; + bool res = Xtensa_LLVM_getInstruction(instr, size, code, code_len, + address); + if (res) { + set_instr_map_data(instr); + } + return res; } const char *Xtensa_reg_name(csh handle, unsigned int id) { - return NULL; + return Xtensa_LLVM_getRegisterName(id); } void Xtensa_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) { + // Done in Xtensa_disasm } const char *Xtensa_insn_name(csh handle, unsigned int id) { +#ifndef CAPSTONE_DIET + if (id >= ARR_SIZE(insn_name_maps)) { + return NULL; + } + return insn_name_maps[id]; +#else return NULL; +#endif } const char *Xtensa_group_name(csh handle, unsigned int id) { +#ifndef CAPSTONE_DIET + return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); +#else return NULL; +#endif } +#ifndef CAPSTONE_DIET void Xtensa_reg_access(const cs_insn *insn, cs_regs regs_read, uint8_t *regs_read_count, cs_regs regs_write, uint8_t *regs_write_count) { -} \ No newline at end of file + uint8_t i; + uint8_t read_count, write_count; + cs_xtensa *detail = &(insn->detail->xtensa); + + read_count = insn->detail->regs_read_count; + write_count = insn->detail->regs_write_count; + + // implicit registers + memcpy(regs_read, insn->detail->regs_read, + read_count * sizeof(insn->detail->regs_read[0])); + memcpy(regs_write, insn->detail->regs_write, + write_count * sizeof(insn->detail->regs_write[0])); + + // explicit registers + for (i = 0; i < detail->op_count; i++) { + cs_xtensa_op *op = &(detail->operands[i]); + switch (op->type) { + case Xtensa_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 Xtensa_OP_MEM: + // registers appeared in memory references always being read + if ((op->mem.base != Xtensa_REG_INVALID) && + !arr_exist(regs_read, read_count, op->mem.base)) { + regs_read[read_count] = (uint16_t)op->mem.base; + read_count++; + } + if ((op->mem.index != Xtensa_REG_INVALID) && + !arr_exist(regs_read, read_count, op->mem.index)) { + regs_read[read_count] = (uint16_t)op->mem.index; + read_count++; + } + if ((insn->detail->writeback) && + (op->mem.base != Xtensa_REG_INVALID) && + !arr_exist(regs_write, write_count, op->mem.base)) { + regs_write[write_count] = + (uint16_t)op->mem.base; + write_count++; + } + default: + break; + } + } + + *regs_read_count = read_count; + *regs_write_count = write_count; +} +#endif diff --git a/arch/Xtensa/XtensaMapping.h b/arch/Xtensa/XtensaMapping.h index 97b665f7c2..4053ee8c0b 100644 --- a/arch/Xtensa/XtensaMapping.h +++ b/arch/Xtensa/XtensaMapping.h @@ -1,6 +1,10 @@ #ifndef XTENSA_MAPPING_H #define XTENSA_MAPPING_H +typedef enum { +#include "XtensaGenCSOpGroup.inc" +} xtensa_op_group; + void Xtensa_init_mri(MCRegisterInfo *mri); void Xtensa_printer(MCInst *MI, SStream *OS, void *info); bool Xtensa_disasm(csh handle, const uint8_t *code, size_t code_len, @@ -9,8 +13,10 @@ const char *Xtensa_reg_name(csh handle, unsigned int id); void Xtensa_insn_id(cs_struct *h, cs_insn *insn, unsigned int id); const char *Xtensa_insn_name(csh handle, unsigned int id); const char *Xtensa_group_name(csh handle, unsigned int id); +#ifndef CAPSTONE_DIET void Xtensa_reg_access(const cs_insn *insn, cs_regs regs_read, uint8_t *regs_read_count, cs_regs regs_write, uint8_t *regs_write_count); +#endif #endif diff --git a/arch/Xtensa/priv.h b/arch/Xtensa/priv.h index d313830269..7914c5c2f2 100644 --- a/arch/Xtensa/priv.h +++ b/arch/Xtensa/priv.h @@ -5,6 +5,6 @@ #define MCRegister unsigned #define MCExpr void #define MCOperand_getExpr(MC) assert(0 && "unimplemented expr") -#define printExpr(E,O) assert(0 && "unimplemented expr") +#define printExpr(E, O) assert(0 && "unimplemented expr") #endif //CAPSTONE_PRIV_H diff --git a/cstool/cstool.c b/cstool/cstool.c index d963988a36..b1706dd5f4 100644 --- a/cstool/cstool.c +++ b/cstool/cstool.c @@ -124,7 +124,7 @@ static Arch all_archs[] = { { "hppa20be", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_BIG_ENDIAN }, { "hppa20w", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_LITTLE_ENDIAN }, { "hppa20wbe", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_BIG_ENDIAN }, - { "xtensa", CS_ARCH_XTENSA, CS_ARCH_XTENSA | CS_MODE_LITTLE_ENDIAN }, + { "xtensa", CS_ARCH_XTENSA, CS_MODE_LITTLE_ENDIAN }, { NULL } }; @@ -345,6 +345,10 @@ static void usage(char *prog) printf(" tc162 tricore V1.6.2\n"); } + if (cs_support(CS_ARCH_XTENSA)) { + printf(" xtensa xtensa\n"); + } + printf("\nExtra options:\n"); printf(" -d show detailed information of the instructions\n"); printf(" -r show detailed information of the real instructions (even for alias)\n"); diff --git a/cstool/cstool_xtensa.c b/cstool/cstool_xtensa.c index 84ff9e540a..df34020b6f 100644 --- a/cstool/cstool_xtensa.c +++ b/cstool/cstool_xtensa.c @@ -5,5 +5,4 @@ void print_insn_detail_xtensa(csh handle, cs_insn *ins) { - } diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index 793110ed5f..e28f4a53fc 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -389,6 +389,7 @@ typedef struct cs_opt_skipdata { #include "tricore.h" #include "alpha.h" #include "hppa.h" +#include "xtensa.h" #define MAX_IMPL_W_REGS 47 #define MAX_IMPL_R_REGS 20 @@ -439,6 +440,7 @@ typedef struct cs_detail { cs_tricore tricore; ///< TriCore architecture cs_alpha alpha; ///< Alpha architecture cs_hppa hppa; ///< HPPA architecture + cs_xtensa xtensa; ///< Xtensa architecture }; } cs_detail; diff --git a/include/capstone/xtensa.h b/include/capstone/xtensa.h index b2633ef797..17a21d78ef 100644 --- a/include/capstone/xtensa.h +++ b/include/capstone/xtensa.h @@ -5,6 +5,9 @@ extern "C" { #endif +#include "cs_operand.h" +#include "platform.h" + /// Xtensa registers typedef enum xtensa_reg { // generated content begin @@ -32,7 +35,7 @@ typedef enum xtensa_reg { // clang-format on // generated content end -} XtensaReg; +} xtensa_reg; /// Xtensa registers typedef enum xtensa_insn { @@ -122,7 +125,51 @@ typedef enum xtensa_insn { // clang-format on // generated content end -} XtensaInsn; +} xtensa_insn; + +typedef enum xtensa_feature { + Xtensa_GRP_INVALID = 0, + Xtensa_GRP_CALL, + Xtensa_GRP_JUMP, + Xtensa_GRP_RET, + // generated content begin + // clang-format off + +Xtensa_FEATURE_HasDensity = 128, + + // clang-format on + // generated content end + Xtensa_GRP_ENDING, ///< mark the end of the list of features +} xtensa_feature; + +typedef enum cs_xtensa_op_type { + Xtensa_OP_INVALID = CS_OP_INVALID, ///< = CS_OP_INVALID (Uninitialized). + Xtensa_OP_REG = CS_OP_REG, ///< = CS_OP_REG (Register operand). + Xtensa_OP_IMM = CS_OP_IMM, ///< = CS_OP_IMM (Immediate operand). + Xtensa_OP_MEM = CS_OP_MEM, ///< = CS_OP_MEM (Memory operand). +} cs_xtensa_op_type; + +typedef struct cs_xtensa_op_mem { + xtensa_reg base; + xtensa_reg index; +} cs_xtensa_op_mem; + +typedef struct cs_xtensa_operand { + cs_xtensa_op_type type; + uint8_t access; + + union { + xtensa_reg reg; + cs_xtensa_op_mem mem; + }; +} cs_xtensa_op; + +#define MAX_XTENSA_OPS 8 + +typedef struct cs_xtensa { + uint8_t op_count; + cs_xtensa_op operands[MAX_XTENSA_OPS]; +} cs_xtensa; #ifdef __cplusplus }