mirror of
https://github.com/capstone-engine/capstone.git
synced 2025-02-07 22:56:19 +00:00
Add operands access support for TriCore
This commit is contained in:
parent
6fc9643161
commit
10a24a9a38
@ -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
|
||||
|
3
Makefile
3
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),)
|
||||
|
@ -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);
|
||||
|
14
Mapping.h
14
Mapping.h
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
21
arch/TriCore/TriCoreLinkage.h
Normal file
21
arch/TriCore/TriCoreLinkage.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
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, ®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 (tricore->update_flags)
|
||||
printf("\tUpdate-flags: True\n");
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user