213 lines
4.7 KiB
C++
213 lines
4.7 KiB
C++
|
//===-EDInst.cpp - LLVM Enhanced Disassembler -----------------------------===//
|
||
|
//
|
||
|
// The LLVM Compiler Infrastructure
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// This file implements the Enhanced Disassembly library's instruction class.
|
||
|
// The instruction is responsible for vending the string representation,
|
||
|
// individual tokens, and operands for a single instruction.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "EDInst.h"
|
||
|
#include "EDDisassembler.h"
|
||
|
#include "EDOperand.h"
|
||
|
#include "EDToken.h"
|
||
|
|
||
|
#include "llvm/MC/EDInstInfo.h"
|
||
|
#include "llvm/MC/MCInst.h"
|
||
|
|
||
|
using namespace llvm;
|
||
|
|
||
|
EDInst::EDInst(llvm::MCInst *inst,
|
||
|
uint64_t byteSize,
|
||
|
EDDisassembler &disassembler,
|
||
|
const llvm::EDInstInfo *info) :
|
||
|
Disassembler(disassembler),
|
||
|
Inst(inst),
|
||
|
ThisInstInfo(info),
|
||
|
ByteSize(byteSize),
|
||
|
BranchTarget(-1),
|
||
|
MoveSource(-1),
|
||
|
MoveTarget(-1) {
|
||
|
OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()];
|
||
|
}
|
||
|
|
||
|
EDInst::~EDInst() {
|
||
|
unsigned int index;
|
||
|
unsigned int numOperands = Operands.size();
|
||
|
|
||
|
for (index = 0; index < numOperands; ++index)
|
||
|
delete Operands[index];
|
||
|
|
||
|
unsigned int numTokens = Tokens.size();
|
||
|
|
||
|
for (index = 0; index < numTokens; ++index)
|
||
|
delete Tokens[index];
|
||
|
|
||
|
delete Inst;
|
||
|
}
|
||
|
|
||
|
uint64_t EDInst::byteSize() {
|
||
|
return ByteSize;
|
||
|
}
|
||
|
|
||
|
int EDInst::stringify() {
|
||
|
if (StringifyResult.valid())
|
||
|
return StringifyResult.result();
|
||
|
|
||
|
if (Disassembler.printInst(String, *Inst))
|
||
|
return StringifyResult.setResult(-1);
|
||
|
|
||
|
String.push_back('\n');
|
||
|
|
||
|
return StringifyResult.setResult(0);
|
||
|
}
|
||
|
|
||
|
int EDInst::getString(const char*& str) {
|
||
|
if (stringify())
|
||
|
return -1;
|
||
|
|
||
|
str = String.c_str();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
unsigned EDInst::instID() {
|
||
|
return Inst->getOpcode();
|
||
|
}
|
||
|
|
||
|
bool EDInst::isBranch() {
|
||
|
if (ThisInstInfo)
|
||
|
return
|
||
|
ThisInstInfo->instructionType == kInstructionTypeBranch ||
|
||
|
ThisInstInfo->instructionType == kInstructionTypeCall;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool EDInst::isMove() {
|
||
|
if (ThisInstInfo)
|
||
|
return ThisInstInfo->instructionType == kInstructionTypeMove;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int EDInst::parseOperands() {
|
||
|
if (ParseResult.valid())
|
||
|
return ParseResult.result();
|
||
|
|
||
|
if (!ThisInstInfo)
|
||
|
return ParseResult.setResult(-1);
|
||
|
|
||
|
unsigned int opIndex;
|
||
|
unsigned int mcOpIndex = 0;
|
||
|
|
||
|
for (opIndex = 0; opIndex < ThisInstInfo->numOperands; ++opIndex) {
|
||
|
if (isBranch() &&
|
||
|
(ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)) {
|
||
|
BranchTarget = opIndex;
|
||
|
}
|
||
|
else if (isMove()) {
|
||
|
if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagSource)
|
||
|
MoveSource = opIndex;
|
||
|
else if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)
|
||
|
MoveTarget = opIndex;
|
||
|
}
|
||
|
|
||
|
EDOperand *operand = new EDOperand(Disassembler, *this, opIndex, mcOpIndex);
|
||
|
|
||
|
Operands.push_back(operand);
|
||
|
}
|
||
|
|
||
|
return ParseResult.setResult(0);
|
||
|
}
|
||
|
|
||
|
int EDInst::branchTargetID() {
|
||
|
if (parseOperands())
|
||
|
return -1;
|
||
|
return BranchTarget;
|
||
|
}
|
||
|
|
||
|
int EDInst::moveSourceID() {
|
||
|
if (parseOperands())
|
||
|
return -1;
|
||
|
return MoveSource;
|
||
|
}
|
||
|
|
||
|
int EDInst::moveTargetID() {
|
||
|
if (parseOperands())
|
||
|
return -1;
|
||
|
return MoveTarget;
|
||
|
}
|
||
|
|
||
|
int EDInst::numOperands() {
|
||
|
if (parseOperands())
|
||
|
return -1;
|
||
|
return Operands.size();
|
||
|
}
|
||
|
|
||
|
int EDInst::getOperand(EDOperand *&operand, unsigned int index) {
|
||
|
if (parseOperands())
|
||
|
return -1;
|
||
|
|
||
|
if (index >= Operands.size())
|
||
|
return -1;
|
||
|
|
||
|
operand = Operands[index];
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int EDInst::tokenize() {
|
||
|
if (TokenizeResult.valid())
|
||
|
return TokenizeResult.result();
|
||
|
|
||
|
if (ThisInstInfo == NULL)
|
||
|
return TokenizeResult.setResult(-1);
|
||
|
|
||
|
if (stringify())
|
||
|
return TokenizeResult.setResult(-1);
|
||
|
|
||
|
return TokenizeResult.setResult(EDToken::tokenize(Tokens,
|
||
|
String,
|
||
|
OperandOrder,
|
||
|
Disassembler));
|
||
|
|
||
|
}
|
||
|
|
||
|
int EDInst::numTokens() {
|
||
|
if (tokenize())
|
||
|
return -1;
|
||
|
return Tokens.size();
|
||
|
}
|
||
|
|
||
|
int EDInst::getToken(EDToken *&token, unsigned int index) {
|
||
|
if (tokenize())
|
||
|
return -1;
|
||
|
token = Tokens[index];
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#ifdef __BLOCKS__
|
||
|
int EDInst::visitTokens(EDTokenVisitor_t visitor) {
|
||
|
if (tokenize())
|
||
|
return -1;
|
||
|
|
||
|
tokvec_t::iterator iter;
|
||
|
|
||
|
for (iter = Tokens.begin(); iter != Tokens.end(); ++iter) {
|
||
|
int ret = visitor(*iter);
|
||
|
if (ret == 1)
|
||
|
return 0;
|
||
|
if (ret != 0)
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|