mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-04 22:07:27 +00:00
847da55716
better in the llvm world. Among other things, this changes: 1. The guts of libedis are now moved into lib/MC/MCDisassembler 2. llvm-mc now depends on lib/MC/MCDisassembler, not tools/edis, so edis and mc don't have to be built in series. 3. lib/MC/MCDisassembler no longer depends on the C api, the C API depends on it. 4. Various code cleanup changes. There is still a lot to be done to make edis fit with the llvm design, but this is an incremental step in the right direction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108869 91177308-0d34-0410-b5e6-96231b3b80d8
208 lines
4.6 KiB
C++
208 lines
4.6 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);
|
|
|
|
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 (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
|