Add operands access support for TriCore

This commit is contained in:
billow 2023-05-30 11:13:03 +08:00
parent 6fc9643161
commit 10a24a9a38
15 changed files with 360 additions and 261 deletions

View File

@ -548,6 +548,7 @@ if (CAPSTONE_TRICORE_SUPPORT)
) )
set(HEADERS_TRICORE set(HEADERS_TRICORE
arch/TriCore/TriCoreDisassembler.h arch/TriCore/TriCoreDisassembler.h
arch/TriCore/TriCoreLinkage.h
arch/TriCore/TriCoreGenAsmWriter.inc arch/TriCore/TriCoreGenAsmWriter.inc
arch/TriCore/TriCoreGenDisassemblerTables.inc arch/TriCore/TriCoreGenDisassemblerTables.inc
arch/TriCore/TriCoreGenInstrInfo.inc arch/TriCore/TriCoreGenInstrInfo.inc

View File

@ -326,11 +326,10 @@ endif
LIBOBJ = 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_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_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX) $(LIBOBJ_WASM) $(LIBOBJ_BPF)
LIBOBJ += $(LIBOBJ_TRICORE) LIBOBJ += $(LIBOBJ_TRICORE)
LIBOBJ += $(OBJDIR)/MCInst.o
ifeq ($(PKG_EXTRA),) ifeq ($(PKG_EXTRA),)

View File

@ -251,3 +251,4 @@ const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
DEFINE_get_detail_op(arm, ARM); DEFINE_get_detail_op(arm, ARM);
DEFINE_get_detail_op(ppc, PPC); DEFINE_get_detail_op(ppc, PPC);
DEFINE_get_detail_op(tricore, TriCore);

View File

@ -21,9 +21,9 @@ typedef struct insn_map {
unsigned short mapid; // The Capstone instruction id unsigned short mapid; // The Capstone instruction id
#ifndef CAPSTONE_DIET #ifndef CAPSTONE_DIET
uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by
///< this instruction ///< this instruction
uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified
///< by this instruction ///< by this instruction
unsigned char groups unsigned char groups
[MAX_NUM_GROUPS]; ///< list of group this instruction belong to [MAX_NUM_GROUPS]; ///< list of group this instruction belong to
bool branch; // branch instruction? bool branch; // branch instruction?
@ -47,7 +47,7 @@ typedef struct {
uint8_t /* cs_ac_type */ access; ///< The access type (read, write) uint8_t /* cs_ac_type */ access; ///< The access type (read, write)
uint8_t /* cs_data_type */ uint8_t /* cs_data_type */
dtypes[MAX_NO_DATA_TYPES]; ///< List of op types. Terminated by dtypes[MAX_NO_DATA_TYPES]; ///< List of op types. Terminated by
///< CS_DATA_TYPE_LAST ///< CS_DATA_TYPE_LAST
} mapping_op; } mapping_op;
#define MAX_NO_INSN_MAP_OPS 16 #define MAX_NO_INSN_MAP_OPS 16
@ -72,14 +72,14 @@ const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
/// Assumes the istruction operands map is called "insn_operands" /// Assumes the istruction operands map is called "insn_operands"
/// Only usable by `auto-sync` archs! /// Only usable by `auto-sync` archs!
#define map_get_op_type(MI, OpNum) \ #define map_get_op_type(MI, OpNum) \
mapping_get_op_type(MI, OpNum, insn_operands, \ mapping_get_op_type(MI, OpNum, (const map_insn_ops *)insn_operands, \
sizeof(insn_operands) / sizeof(insn_operands[0])) sizeof(insn_operands) / sizeof(insn_operands[0]))
/// Macro for easier access of operand access flags from the map. /// Macro for easier access of operand access flags from the map.
/// Assumes the istruction operands map is called "insn_operands" /// Assumes the istruction operands map is called "insn_operands"
/// Only usable by `auto-sync` archs! /// Only usable by `auto-sync` archs!
#define map_get_op_access(MI, OpNum) \ #define map_get_op_access(MI, OpNum) \
mapping_get_op_access(MI, OpNum, insn_operands, \ mapping_get_op_access(MI, OpNum, (const map_insn_ops *)insn_operands, \
sizeof(insn_operands) / \ sizeof(insn_operands) / \
sizeof(insn_operands[0])) sizeof(insn_operands[0]))
@ -112,6 +112,7 @@ void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size);
DECL_get_detail_op(arm, ARM); DECL_get_detail_op(arm, ARM);
DECL_get_detail_op(ppc, PPC); DECL_get_detail_op(ppc, PPC);
DECL_get_detail_op(tricore, TriCore);
/// Increments the detail->arch.op_count by one. /// Increments the detail->arch.op_count by one.
#define DEFINE_inc_detail_op_count(arch, ARCH) \ #define DEFINE_inc_detail_op_count(arch, ARCH) \
@ -131,6 +132,8 @@ DEFINE_inc_detail_op_count(arm, ARM);
DEFINE_dec_detail_op_count(arm, ARM); DEFINE_dec_detail_op_count(arm, ARM);
DEFINE_inc_detail_op_count(ppc, PPC); DEFINE_inc_detail_op_count(ppc, PPC);
DEFINE_dec_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. /// Returns true if a memory operand is currently edited.
static inline bool doing_mem(const MCInst *MI) static inline bool doing_mem(const MCInst *MI)
@ -154,6 +157,7 @@ static inline void set_doing_mem(const MCInst *MI, bool status)
DEFINE_get_arch_detail(arm, ARM); DEFINE_get_arch_detail(arm, ARM);
DEFINE_get_arch_detail(ppc, PPC); DEFINE_get_arch_detail(ppc, PPC);
DEFINE_get_arch_detail(tricore, TriCore);
static inline bool detail_is_set(const MCInst *MI) static inline bool detail_is_set(const MCInst *MI)
{ {

View File

@ -27,31 +27,8 @@
#include "../../MathExtras.h" #include "../../MathExtras.h"
#include "TriCoreDisassembler.h" #include "TriCoreDisassembler.h"
#include "TriCoreMapping.h"
static bool readInstruction16(const uint8_t *code, size_t code_len, #include "TriCoreLinkage.h"
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;
}
static unsigned getReg(MCRegisterInfo *MRI, unsigned RC, unsigned RegNo) 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, uint64_t address, void *info,
const uint8_t *decoderTable16) const uint8_t *decoderTable16)
{ {
uint16_t insn16; if (code_len < 2) {
DecodeStatus Result;
if (!readInstruction16(code, code_len, &insn16)) {
return false; return false;
} }
// Calling the auto-generated decoder function. uint16_t insn16 = readBytes16(MI, code);
Result = decodeInstruction_2(decoderTable16, MI, insn16, address, info, DecodeStatus Result = decodeInstruction_2(decoderTable16, MI, insn16,
0); address, info, 0);
if (Result != MCDisassembler_Fail) { if (Result != MCDisassembler_Fail) {
*size = 2; *size = 2;
return true; return true;
@ -1505,14 +1480,12 @@ static inline bool tryGetInstruction32(const uint8_t *code, size_t code_len,
uint64_t address, void *info, uint64_t address, void *info,
const uint8_t *decoderTable32) const uint8_t *decoderTable32)
{ {
uint32_t insn32; if (code_len < 4) {
DecodeStatus Result;
if (!readInstruction32(code, code_len, &insn32)) {
return false; return false;
} }
// Calling the auto-generated decoder function. uint32_t insn32 = readBytes32(MI, code);
Result = decodeInstruction_4(decoderTable32, MI, insn32, address, info, DecodeStatus Result = decodeInstruction_4(decoderTable32, MI, insn32,
0); address, info, 0);
if (Result != MCDisassembler_Fail) { if (Result != MCDisassembler_Fail) {
*size = 4; *size = 4;
return true; return true;
@ -1520,9 +1493,9 @@ static inline bool tryGetInstruction32(const uint8_t *code, size_t code_len,
return false; return false;
} }
bool TriCore_getInstruction(csh ud, const uint8_t *code, size_t code_len, static bool getInstruction(csh ud, const uint8_t *code, size_t code_len,
MCInst *MI, uint16_t *size, uint64_t address, MCInst *MI, uint16_t *size, uint64_t address,
void *info) void *info)
{ {
if (!ud) { if (!ud) {
return false; return false;
@ -1569,7 +1542,19 @@ bool TriCore_getInstruction(csh ud, const uint8_t *code, size_t code_len,
DecoderTable32); 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, InitMCRegisterInfo(TriCoreRegDesc, 45, RA, PC,

View File

@ -12,12 +12,7 @@
#include "../../MCRegisterInfo.h" #include "../../MCRegisterInfo.h"
#include "../../MCInst.h" #include "../../MCInst.h"
void TriCore_init(MCRegisterInfo *MRI); void TriCore_init_mri(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);
bool TriCore_getFeatureBits(unsigned int mode, unsigned int feature); bool TriCore_getFeatureBits(unsigned int mode, unsigned int feature);
#endif #endif

View File

@ -26,8 +26,8 @@
#include "../../MathExtras.h" #include "../../MathExtras.h"
#include "../../SStream.h" #include "../../SStream.h"
#include "../../utils.h" #include "../../utils.h"
#include "TriCoreInstPrinter.h"
#include "TriCoreMapping.h" #include "TriCoreMapping.h"
#include "TriCoreLinkage.h"
static const char *getRegisterName(unsigned RegNo); 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); 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 #define GET_INSTRINFO_ENUM
#include "TriCoreGenInstrInfo.inc" #include "TriCoreGenInstrInfo.inc"
@ -51,39 +43,47 @@ void TriCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
#include "TriCoreGenRegisterInfo.inc" #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)
static inline void fill_tricore_register(MCInst *MI, uint32_t reg)
{ {
if (!(MI->csh->detail == CS_OPT_ON && MI->flat_insn->detail)) op->type |= TRICORE_OP_MEM;
return; op->mem.base = base;
cs_tricore *tricore = &MI->flat_insn->detail->tricore; op->mem.disp = disp;
tricore->operands[tricore->op_count].type = TRICORE_OP_REG;
tricore->operands[tricore->op_count].reg = reg;
tricore->op_count++;
} }
static inline void fill_tricore_imm(MCInst *MI, int32_t imm) 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; return;
cs_tricore *tricore = &MI->flat_insn->detail->tricore; cs_tricore_op *op = TriCore_get_detail_op(MI, 0);
if (tricore->op_count >= 1 && op->type = TRICORE_OP_REG;
tricore->operands[tricore->op_count - 1].type == TRICORE_OP_REG && op->reg = reg;
fixup_op_mem(MI, tricore->operands[tricore->op_count - 1].reg, TriCore_inc_op_count(MI);
imm)) { }
static inline void fill_imm(MCInst *MI, int32_t imm)
{
if (!detail_is_set(MI))
return; 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++; 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_LDMST:
case TRICORE_INS_LDLCX: case TRICORE_INS_LDLCX:
case TRICORE_INS_LD_A: 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_SWAPMSK_W:
case TRICORE_INS_LEA: case TRICORE_INS_LEA:
case TRICORE_INS_LHA: { case TRICORE_INS_LHA: {
switch (MCInst_getOpcode(pInst)) { switch (MCInst_getOpcode(MI)) {
case TRICORE_LDMST_abs: case TRICORE_LDMST_abs:
case TRICORE_LDLCX_abs: case TRICORE_LDLCX_abs:
case TRICORE_LD_A_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; return false;
} }
} }
cs_tricore *tc = &pInst->flat_insn->detail->tricore; cs_tricore_op *op = TriCore_get_detail_op(MI, -1);
fill_mem(tc, reg, disp); op->type = 0;
set_mem(op, reg, disp);
return true; return true;
} }
} }
return false; 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) static void printOperand(MCInst *MI, int OpNum, SStream *O)
{ {
MCOperand *Op;
if (OpNum >= MI->size) if (OpNum >= MI->size)
return; return;
Op = MCInst_getOperand(MI, OpNum); MCOperand *Op = MCInst_getOperand(MI, OpNum);
if (MCOperand_isReg(Op)) { if (MCOperand_isReg(Op)) {
unsigned reg = MCOperand_getReg(Op); unsigned reg = MCOperand_getReg(Op);
SStream_concat(O, "%%%s", getRegisterName(reg)); SStream_concat(O, "%%%s", getRegisterName(reg));
fill_tricore_register(MI, reg); fill_reg(MI, reg);
} else if (MCOperand_isImm(Op)) { } else if (MCOperand_isImm(Op)) {
int64_t Imm = MCOperand_getImm(Op); int64_t Imm = MCOperand_getImm(Op);
printInt64(O, Imm);
if (Imm >= 0) { fill_imm(MI, (int32_t)Imm);
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);
} }
} }
@ -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); int32_t imm = (int32_t)MCOperand_getImm(MO);
imm = sign_ext_n(imm, n); imm = sign_ext_n(imm, n);
printInt32(O, imm); printInt32(O, imm);
fill_tricore_imm(MI, imm); fill_imm(MI, imm);
} else } else
printOperand(MI, OpNum, O); 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); off4_fixup(MI, &imm);
} }
if (imm >= 0) { printInt64(O, imm);
if (imm > HEX_THRESHOLD) fill_imm(MI, imm);
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);
} else } else
printOperand(MI, OpNum, O); 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); uint32_t imm = (uint32_t)MCOperand_getImm(MO);
imm = ((imm & 0x3C000) << 14) | (imm & 0x3fff); imm = ((imm & 0x3C000) << 14) | (imm & 0x3fff);
SStream_concat(O, "0x%x", imm); SStream_concat(O, "0x%x", imm);
fill_tricore_imm(MI, (int32_t)imm); fill_imm(MI, (int32_t)imm);
} else } else
printOperand(MI, OpNum, O); printOperand(MI, OpNum, O);
} }
@ -311,7 +280,7 @@ static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O)
} }
printUInt32(O, disp); printUInt32(O, disp);
fill_tricore_imm(MI, disp); fill_imm(MI, disp);
} else } else
printOperand(MI, OpNum, O); printOperand(MI, OpNum, O);
} }
@ -356,7 +325,7 @@ static void printDisp15Imm(MCInst *MI, int OpNum, SStream *O)
} }
printUInt32(O, disp); printUInt32(O, disp);
fill_tricore_imm(MI, disp); fill_imm(MI, disp);
} else } else
printOperand(MI, OpNum, O); printOperand(MI, OpNum, O);
} }
@ -381,7 +350,7 @@ static void printDisp8Imm(MCInst *MI, int OpNum, SStream *O)
} }
printUInt32(O, disp); printUInt32(O, disp);
fill_tricore_imm(MI, disp); fill_imm(MI, disp);
} else } else
printOperand(MI, OpNum, O); printOperand(MI, OpNum, O);
} }
@ -426,7 +395,7 @@ static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O)
} }
printUInt32(O, disp); printUInt32(O, disp);
fill_tricore_imm(MI, disp); fill_imm(MI, disp);
} else } else
printOperand(MI, OpNum, O); printOperand(MI, OpNum, O);
} }
@ -467,7 +436,7 @@ static void printOExtImm_4(MCInst *MI, int OpNum, SStream *O)
imm = 0b11111111111111111111111111100000 | (imm << 1); imm = 0b11111111111111111111111111100000 | (imm << 1);
printInt32(O, imm); printInt32(O, imm);
fill_tricore_imm(MI, imm); fill_imm(MI, imm);
} else } else
printOperand(MI, OpNum, O); printOperand(MI, OpNum, O);
} }
@ -485,7 +454,7 @@ static void set_mem_access(MCInst *MI, unsigned int access)
#include "TriCoreGenAsmWriter.inc" #include "TriCoreGenAsmWriter.inc"
const char *TriCore_getRegisterName(csh handle, unsigned int id) const char *TriCore_LLVM_getRegisterName(unsigned int id)
{ {
#ifndef CAPSTONE_DIET #ifndef CAPSTONE_DIET
return getRegisterName(id); return getRegisterName(id);
@ -494,9 +463,10 @@ const char *TriCore_getRegisterName(csh handle, unsigned int id)
#endif #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

View File

@ -1,18 +0,0 @@
/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 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

View File

@ -0,0 +1,21 @@
/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 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

View File

@ -5,10 +5,13 @@
#include <stdio.h> // debug #include <stdio.h> // debug
#include <string.h> #include <string.h>
#include <assert.h>
#include "../../utils.h" #include "../../utils.h"
#include "../../cs_simple_types.h"
#include "TriCoreMapping.h" #include "TriCoreMapping.h"
#include "TriCoreLinkage.h"
#define GET_INSTRINFO_ENUM #define GET_INSTRINFO_ENUM
@ -30,52 +33,41 @@ static insn_map insns[] = {
#include "TriCoreGenCSMappingInsn.inc" #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) 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;
if (h->detail) {
#ifndef CAPSTONE_DIET #ifndef CAPSTONE_DIET
memcpy(insn->detail->regs_read, insns[i].regs_use, static tricore_reg flag_regs[] = { TRICORE_REG_PSW };
sizeof(insns[i].regs_use)); #endif // CAPSTONE_DIET
insn->detail->regs_read_count =
(uint8_t)count_positive(insns[i].regs_use);
memcpy(insn->detail->regs_write, insns[i].regs_mod, static inline void check_updates_flags(MCInst *MI)
sizeof(insns[i].regs_mod)); {
insn->detail->regs_write_count = #ifndef CAPSTONE_DIET
(uint8_t)count_positive(insns[i].regs_mod); if (!MI->flat_insn->detail)
return;
memcpy(insn->detail->groups, insns[i].groups, cs_detail *detail = MI->flat_insn->detail;
sizeof(insns[i].groups)); for (int i = 0; i < detail->regs_write_count; ++i) {
insn->detail->groups_count = if (detail->regs_write[i] == 0)
(uint8_t)count_positive8(insns[i].groups); return;
for (int j = 0; j < ARR_SIZE(flag_regs); ++j) {
if (insns[i].branch || insns[i].indirect_branch) { if (detail->regs_write[i] == flag_regs[j]) {
// this insn also belongs to JUMP group. add JUMP group detail->tricore.update_flags = true;
insn->detail return;
->groups[insn->detail->groups_count] =
TRICORE_GRP_JUMP;
insn->detail->groups_count++;
} }
#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 #ifndef CAPSTONE_DIET
@ -130,4 +122,120 @@ const char *TriCore_group_name(csh handle, unsigned int id)
#endif #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 #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

View File

@ -6,8 +6,6 @@
#include <capstone/capstone.h> #include <capstone/capstone.h>
unsigned int TriCore_map_insn_id(cs_struct *h, unsigned int id);
// given internal insn id, return public instruction info // given internal insn id, return public instruction info
void TriCore_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id); 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); const char *TriCore_group_name(csh handle, unsigned int id);
cs_err TRICORE_global_init(cs_struct *ud); void TriCore_reg_access(const cs_insn *insn, cs_regs regs_read,
cs_err TRICORE_option(cs_struct *handle, cs_opt_type type, size_t value); 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 #endif

View File

@ -4,9 +4,9 @@
#ifdef CAPSTONE_HAS_TRICORE #ifdef CAPSTONE_HAS_TRICORE
#include "../../utils.h" #include "../../utils.h"
#include "TriCoreDisassembler.h"
#include "TriCoreInstPrinter.h"
#include "TriCoreMapping.h" #include "TriCoreMapping.h"
#include "TriCoreModule.h"
#include "TriCoreDisassembler.h"
cs_err TRICORE_global_init(cs_struct *ud) 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)); mri = cs_mem_malloc(sizeof(*mri));
TriCore_init(mri); TriCore_init_mri(mri);
ud->printer = TriCore_printInst; ud->printer = TriCore_printInst;
ud->printer_info = mri; ud->printer_info = mri;
ud->getinsn_info = mri; ud->getinsn_info = mri;
ud->disasm = TriCore_getInstruction; ud->disasm = TriCore_getInstruction;
ud->post_printer = TriCore_post_printer; ud->post_printer = NULL;
ud->reg_name = TriCore_getRegisterName; ud->reg_name = TriCore_getRegisterName;
ud->insn_id = TriCore_get_insn_id; ud->insn_id = TriCore_get_insn_id;
ud->insn_name = TriCore_insn_name; ud->insn_name = TriCore_insn_name;
ud->group_name = TriCore_group_name; ud->group_name = TriCore_group_name;
#ifndef CAPSTONE_DIET
ud->reg_access = TriCore_reg_access;
#endif
return CS_ERR_OK; return CS_ERR_OK;
} }

View File

@ -265,11 +265,11 @@ typedef enum {
CS_DATA_TYPE_Glue = CS_DATA_TYPE_Glue =
189, // This glues nodes together during pre-RA sched 189, // This glues nodes together during pre-RA sched
CS_DATA_TYPE_isVoid = 190, // This has no value CS_DATA_TYPE_isVoid = 190, // This has no value
CS_DATA_TYPE_Untyped = 191, // This value takes a register, but has CS_DATA_TYPE_Untyped = 191, // This value takes a register, but has
// unspecified type. The register class // unspecified type. The register class
// will be determined by the opcode. // will be determined by the opcode.
CS_DATA_TYPE_funcref = 192, // WebAssembly's funcref type CS_DATA_TYPE_funcref = 192, // WebAssembly's funcref type
CS_DATA_TYPE_externref = 193, // WebAssembly's externref type CS_DATA_TYPE_externref = 193, // WebAssembly's externref type

View File

@ -34,39 +34,51 @@ void print_insn_detail_tricore(csh handle, cs_insn *ins)
op->imm); op->imm);
break; break;
case TRICORE_OP_MEM: case TRICORE_OP_MEM:
printf("\t\toperands[%u].type: MEM\n", i); printf("\t\toperands[%u].type: MEM\n"
if (op->mem.base != TRICORE_REG_INVALID) "\t\t\t.mem.base: REG = %s\n"
printf("\t\t\toperands[%u].mem.base: REG = %s\n", "\t\t\t.mem.disp: 0x%x\n",
i, cs_reg_name(handle, op->mem.base)); i, cs_reg_name(handle, op->mem.base),
if (op->mem.disp != 0) op->mem.disp);
printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i,
op->mem.disp);
break; break;
} }
// Print out all registers accessed by this instruction (either implicit or switch (op->access) {
// explicit) default:
if (!cs_regs_access(handle, ins, regs_read, &regs_read_count, break;
regs_write, &regs_write_count)) { case CS_AC_READ:
if (regs_read_count) { printf("\t\t\t.access: READ\n");
printf("\tRegisters read:"); break;
for (i = 0; i < regs_read_count; i++) { case CS_AC_WRITE:
printf(" %s", printf("\t\t\t.access: WRITE\n");
cs_reg_name(handle, break;
regs_read[i])); case CS_AC_READ | CS_AC_WRITE:
} printf("\t\t\t.access: READ | WRITE\n");
printf("\n"); break;
}
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");
}
} }
} }
// Print out all registers accessed by this instruction (either implicit or
// explicit)
if (!cs_regs_access(handle, ins, regs_read, &regs_read_count,
regs_write, &regs_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 (tricore->update_flags)
printf("\tUpdate-flags: True\n");
} }

View File

@ -18,40 +18,46 @@ extern "C" {
#pragma warning(disable : 4201) #pragma warning(disable : 4201)
#endif #endif
//> Operand type for instruction's operands /// Operand type for instruction's operands
typedef enum tricore_op_type { typedef enum tricore_op_type {
TRICORE_OP_INVALID = 0, // = CS_OP_INVALID (Uninitialized). TRICORE_OP_INVALID = CS_OP_INVALID, ///< CS_OP_INVALID (Uninitialized).
TRICORE_OP_REG, // = CS_OP_REG (Register operand). TRICORE_OP_REG = CS_OP_REG, ///< CS_OP_REG (Register operand).
TRICORE_OP_IMM, // = CS_OP_IMM (Immediate operand). TRICORE_OP_IMM = CS_OP_IMM, ///< CS_OP_IMM (Immediate operand).
TRICORE_OP_MEM, // = CS_OP_MEM (Memory operand). TRICORE_OP_MEM = CS_OPT_MEM, ///< CS_OP_MEM (Memory operand).
} tricore_op_type; } tricore_op_type;
// Instruction's operand referring to memory /// Instruction's operand referring to memory
// This is associated with TRICORE_OP_MEM operand type above /// This is associated with TRICORE_OP_MEM operand type above
typedef struct tricore_op_mem { typedef struct tricore_op_mem {
uint8_t base; // base register uint8_t base; ///< base register
int32_t disp; // displacement/offset value int32_t disp; ///< displacement/offset value
} tricore_op_mem; } tricore_op_mem;
// Instruction operand /// Instruction operand
typedef struct cs_tricore_op { typedef struct cs_tricore_op {
tricore_op_type type; // operand type tricore_op_type type; ///< operand type
union { union {
unsigned int reg; // register value for REG operand unsigned int reg; ///< register value for REG operand
int32_t imm; // immediate value for IMM operand int32_t imm; ///< immediate value for IMM operand
tricore_op_mem mem; // base/disp value for MEM 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; } cs_tricore_op;
// Instruction structure #define TRICORE_OP_COUNT 8
/// Instruction structure
typedef struct cs_tricore { typedef struct cs_tricore {
// Number of operands of this instruction, uint8_t op_count; ///< number of operands of this instruction.
// or 0 when instruction has no operand. cs_tricore_op
uint8_t op_count; operands[TRICORE_OP_COUNT]; ///< operands for this instruction.
cs_tricore_op operands[8]; // 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; } cs_tricore;
//> TriCore registers /// TriCore registers
typedef enum tricore_reg { typedef enum tricore_reg {
// generate content <TriCoreGenCSRegEnum.inc> begin // generate content <TriCoreGenCSRegEnum.inc> begin
// clang-format off // clang-format off
@ -123,7 +129,7 @@ typedef enum tricore_reg {
// generate content <TriCoreGenCSRegEnum.inc> end // generate content <TriCoreGenCSRegEnum.inc> end
} tricore_reg; } tricore_reg;
//> TriCore instruction /// TriCore instruction
typedef enum tricore_insn { typedef enum tricore_insn {
TRICORE_INS_INVALID = 0, TRICORE_INS_INVALID = 0,
// generate content <TriCoreGenCSInsnEnum.inc> begin // generate content <TriCoreGenCSInsnEnum.inc> begin
@ -525,13 +531,13 @@ typedef enum tricore_insn {
TRICORE_INS_ENDING, // <-- mark the end of the list of instructions TRICORE_INS_ENDING, // <-- mark the end of the list of instructions
} tricore_insn; } tricore_insn;
//> Group of TriCore instructions /// Group of TriCore instructions
typedef enum tricore_insn_group { typedef enum tricore_insn_group {
TRICORE_GRP_INVALID, ///< = CS_GRP_INVALID TRICORE_GRP_INVALID, ///< = CS_GRP_INVALID
//> Generic groups /// Generic groups
TRICORE_GRP_CALL, ///< = CS_GRP_CALL TRICORE_GRP_CALL, ///< = CS_GRP_CALL
TRICORE_GRP_JUMP, ///< = CS_GRP_JUMP TRICORE_GRP_JUMP, ///< = CS_GRP_JUMP
TRICORE_GRP_ENDING, ///< = mark the end of the list of groups TRICORE_GRP_ENDING, ///< mark the end of the list of groups
} tricore_insn_group; } tricore_insn_group;
typedef enum tricore_feature_t { typedef enum tricore_feature_t {
@ -551,7 +557,7 @@ typedef enum tricore_feature_t {
// clang-format on // clang-format on
// generate content <TriCoreGenCSFeatureEnum.inc> end // generate content <TriCoreGenCSFeatureEnum.inc> 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; } tricore_feature;
#ifdef __cplusplus #ifdef __cplusplus