Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ set(SOURCES_ENGINE
cs.c
MCInst.c
MCInstrDesc.c
MCInstPrinter.c
MCRegisterInfo.c
SStream.c
utils.c
Expand All @@ -100,6 +101,7 @@ set(HEADERS_ENGINE
MCFixedLenDisassembler.h
MCInst.h
MCInstrDesc.h
MCInstPrinter.h
MCRegisterInfo.h
SStream.h
utils.h
Expand Down Expand Up @@ -201,20 +203,13 @@ if (CAPSTONE_MIPS_SUPPORT)
arch/Mips/MipsDisassembler.h
arch/Mips/MipsGenAsmWriter.inc
arch/Mips/MipsGenDisassemblerTables.inc
arch/Mips/MipsGenInstrInfo.inc
arch/Mips/MipsGenRegisterInfo.inc
arch/Mips/MipsGenSubtargetInfo.inc
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsMapping.h
arch/Mips/MipsMappingInsn.inc
)
set(HEADERS_MIPS
arch/Mips/MipsDisassembler.h
arch/Mips/MipsGenAsmWriter.inc
arch/Mips/MipsGenDisassemblerTables.inc
arch/Mips/MipsGenInstrInfo.inc
arch/Mips/MipsGenRegisterInfo.inc
arch/Mips/MipsGenSubtargetInfo.inc
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsMapping.h
)
Expand Down
114 changes: 114 additions & 0 deletions MCInstPrinter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// Created by Phosphorus15 on 2021/5/14.
//
#include "MCInstPrinter.h"
#include "MCInst.h"

static bool MCInstPrinter_matchAliasCondition(
const MCInst *MI, unsigned *OpIdx, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const AliasPatternCond *Cond, bool *OrPredicateResult) {
// FIXME so here's on problem we ought to detect feature bits here
if (Cond->Kind == AliasPatternCond_K_Feature ||
Cond->Kind == AliasPatternCond_K_NegFeature)
return true; // STI->getFeatureBits().test(C.Value);
// For feature tests where just one feature is required in a list, set the
// predicate result bit to whether the expression will return true, and only
// return the real result at the end of list marker.
if (Cond->Kind == AliasPatternCond_K_OrFeature) {
// *OrPredicateResult |= STI->getFeatureBits().test(C.Value);
return true;
}
if (Cond->Kind == AliasPatternCond_K_OrNegFeature) {
// *OrPredicateResult |= !(STI->getFeatureBits().test(C.Value));
return true;
}
if (Cond->Kind == AliasPatternCond_K_EndOrFeatures) {
bool Res = *OrPredicateResult;
*OrPredicateResult = false;
return Res;
}

MCOperand *Opnd = MCInst_getOperand((MCInst *)MI, *OpIdx);
*OpIdx = *OpIdx + 1;
switch (Cond->Kind) {
case AliasPatternCond_K_Imm:
// Operand must be a specific immediate.
return MCOperand_isImm(Opnd) && MCOperand_getImm(Opnd) == Cond->Value;
case AliasPatternCond_K_Reg:
// Operand must be a specific register.
return MCOperand_isReg(Opnd) && MCOperand_getReg(Opnd) == Cond->Value;
case AliasPatternCond_K_TiedReg:
// Operand must match the register of another operand.
return MCOperand_isReg(Opnd) &&
MCOperand_getReg(Opnd) ==
MCOperand_getReg(MCInst_getOperand((MCInst *)MI, Cond->Value));
case AliasPatternCond_K_RegClass:
// Operand must be a register in this class. Value is a register class id.
return MCOperand_isReg(Opnd) &&
MCRegisterClass_contains(
MCRegisterInfo_getRegClass(MRI, Cond->Value),
MCOperand_getReg(Opnd));
case AliasPatternCond_K_Custom:
// Operand must match some custom criteria.
// TODO might affect something return M.ValidateMCOperand(Opnd,
// *STI, C.Value);
return false;
case AliasPatternCond_K_Ignore:
// Operand can be anything.
return true;
case AliasPatternCond_K_Feature:
case AliasPatternCond_K_NegFeature:
case AliasPatternCond_K_OrFeature:
case AliasPatternCond_K_OrNegFeature:
case AliasPatternCond_K_EndOrFeatures:
default:
return false;
// TODO: Impossible to reach
// llvm_unreachable("handled earlier");
}
}

const char *MCInstPrinter_matchAliasPatterns(
const MCInst *MI, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const char *AsmStrings[], unsigned len) {

// Binary search by opcode. Return false if there are no aliases for this
// opcode.
PatternsForOpcode *It =
Binary_Search(OpToPatterns, MCInst_getOpcode(MI), len);
if (It == NULL || It->Opcode != MCInst_getOpcode(MI))
return NULL;

// Try all patterns for this opcode.
uint32_t AsmStrOffset = ~0U;

for (unsigned i = It->PatternStart; i < It->PatternStart + It->NumPatterns;
i++) {
const AliasPattern Pattern = Patterns[i];
if (MCInst_getNumOperands(MI) != Pattern.NumOperands)
return NULL;
unsigned OpIdx = 0;
bool OrPredicateResult = false;
bool fallThrough = true;
for (unsigned j = Pattern.AliasCondStart;
j < Pattern.AliasCondStart + Pattern.NumConds; j++) {
fallThrough &= MCInstPrinter_matchAliasCondition(
MI, &OpIdx, OpToPatterns, Patterns, Conds, &Conds[j],
&OrPredicateResult);
if (!fallThrough)
break;
}
if (fallThrough) {
AsmStrOffset = Pattern.AsmStrOffset;
break;
}
}

// If no alias matched, don't print an alias.
if (AsmStrOffset == ~0U)
return NULL;

return (const char *)((*AsmStrings) + AsmStrOffset);
}
67 changes: 67 additions & 0 deletions MCInstPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// Created by Phosphorus15 on 2021/5/14.
//

#ifndef CAPSTONE_MCINSTPRINTER_H
#define CAPSTONE_MCINSTPRINTER_H

#include "MCInst.h"
#include "capstone/platform.h"
#include "stdlib.h"

// TODO we'll need this later
const MCRegisterInfo *MRI;

typedef enum CondKind {
AliasPatternCond_K_Feature, // Match only if a feature is enabled.
AliasPatternCond_K_NegFeature, // Match only if a feature is disabled.
AliasPatternCond_K_OrFeature, // Match only if one of a set of features is
// enabled.
AliasPatternCond_K_OrNegFeature, // Match only if one of a set of features is
// disabled.
AliasPatternCond_K_EndOrFeatures, // Note end of list of K_Or(Neg)?Features.
AliasPatternCond_K_Ignore, // Match any operand.
AliasPatternCond_K_Reg, // Match a specific register.
AliasPatternCond_K_TiedReg, // Match another already matched register.
AliasPatternCond_K_Imm, // Match a specific immediate.
AliasPatternCond_K_RegClass, // Match registers in a class.
AliasPatternCond_K_Custom, // Call custom matcher by index.
} CondKind;

typedef struct PatternsForOpcode {
uint32_t Opcode;
uint16_t PatternStart;
uint16_t NumPatterns;
} PatternsForOpcode;

typedef struct AliasPattern {
uint32_t AsmStrOffset;
uint32_t AliasCondStart;
uint8_t NumOperands;
uint8_t NumConds;
} AliasPattern;

typedef struct AliasPatternCond {
CondKind Kind;
uint32_t Value;
} AliasPatternCond;

static inline int cmp_less(const void *l, const void *r) {
return ((signed)((const PatternsForOpcode *)l)->Opcode) -
((signed)((const PatternsForOpcode *)r)->Opcode);
}

// Binary Search Implementation - let's use bsearch for now
static inline PatternsForOpcode *Binary_Search(const PatternsForOpcode *OpToPatterns,
const unsigned opcode, unsigned len) {
return bsearch((void *)&opcode, (void *)OpToPatterns, len,
sizeof(PatternsForOpcode), cmp_less);
}


const char *MCInstPrinter_matchAliasPatterns(
const MCInst *MI, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const char *AsmStrings[], unsigned len);

#endif // CAPSTONE_MCINSTPRINTER_H
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ 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)/MCInstPrinter.o $(OBJDIR)/MCRegisterInfo.o
LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_RISCV) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ)
LIBOBJ += $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX) $(LIBOBJ_WASM) $(LIBOBJ_BPF)
LIBOBJ += $(OBJDIR)/MCInst.o
Expand Down
30 changes: 30 additions & 0 deletions MathExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,4 +439,34 @@ static inline unsigned int countLeadingZeros(int x)
return count;
}

/// \brief Count number of 0's from the least significant bit to the most
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
static inline unsigned int countTrailingZeros(int x) {
int i;
const unsigned bits = sizeof(x) * 8 - 1;
unsigned count = 0;

if (x < 0) {
return 0;
}

for (i = bits; --i;) {
if (x % 2 == 0)
count++;
else
break;
}

// considering it is signed integer
if (count == bits - 1 && x > 0)
count++;

return count;
}

#endif
Loading