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
arch/TriCore/TriCoreDisassembler.h
arch/TriCore/TriCoreLinkage.h
arch/TriCore/TriCoreGenAsmWriter.inc
arch/TriCore/TriCoreGenDisassemblerTables.inc
arch/TriCore/TriCoreGenInstrInfo.inc

View File

@ -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),)

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(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
#ifndef CAPSTONE_DIET
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
///< by this instruction
///< by this instruction
unsigned char groups
[MAX_NUM_GROUPS]; ///< list of group this instruction belong to
bool branch; // branch instruction?
@ -47,7 +47,7 @@ typedef struct {
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
///< CS_DATA_TYPE_LAST
} mapping_op;
#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"
/// Only usable by `auto-sync` archs!
#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]))
/// Macro for easier access of operand access flags from the map.
/// Assumes the istruction operands map is called "insn_operands"
/// Only usable by `auto-sync` archs!
#define map_get_op_access(MI, OpNum) \
mapping_get_op_access(MI, OpNum, insn_operands, \
mapping_get_op_access(MI, OpNum, (const map_insn_ops *)insn_operands, \
sizeof(insn_operands) / \
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(ppc, PPC);
DECL_get_detail_op(tricore, TriCore);
/// Increments the detail->arch.op_count by one.
#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_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)
@ -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(ppc, PPC);
DEFINE_get_arch_detail(tricore, TriCore);
static inline bool detail_is_set(const MCInst *MI)
{

View File

@ -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,

View File

@ -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

View File

@ -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 fill_tricore_register(MCInst *MI, uint32_t reg)
static inline void set_mem(cs_tricore_op *op, uint8_t base, int32_t disp)
{
if (!(MI->csh->detail == CS_OPT_ON && MI->flat_insn->detail))
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++;
op->type |= TRICORE_OP_MEM;
op->mem.base = base;
op->mem.disp = disp;
}
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;
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)) {
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_imm(MCInst *MI, int32_t 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

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 <string.h>
#include <assert.h>
#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;
if (h->detail) {
#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);
static tricore_reg flag_regs[] = { TRICORE_REG_PSW };
#endif // CAPSTONE_DIET
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++;
static inline void check_updates_flags(MCInst *MI)
{
#ifndef CAPSTONE_DIET
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

View File

@ -6,8 +6,6 @@
#include <capstone/capstone.h>
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

View File

@ -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;
}

View File

@ -265,11 +265,11 @@ typedef enum {
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_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_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

View File

@ -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, &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");
}
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, &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)
#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 <TriCoreGenCSRegEnum.inc> begin
// clang-format off
@ -123,7 +129,7 @@ typedef enum tricore_reg {
// generate content <TriCoreGenCSRegEnum.inc> end
} tricore_reg;
//> TriCore instruction
/// TriCore instruction
typedef enum tricore_insn {
TRICORE_INS_INVALID = 0,
// 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_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 <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;
#ifdef __cplusplus