summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2011-08-08 18:56:44 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2011-08-08 18:56:44 +0000
commit41ab14b725c8f2bb3e54553d0d7d96ff184786b1 (patch)
tree72f291595c549382084181fd41ac671dbbee62f7 /lib
parentc13464f3c1148a7096356f34f33932d3e258570e (diff)
downloadllvm-41ab14b725c8f2bb3e54553d0d7d96ff184786b1.tar.gz
llvm-41ab14b725c8f2bb3e54553d0d7d96ff184786b1.tar.bz2
llvm-41ab14b725c8f2bb3e54553d0d7d96ff184786b1.tar.xz
Add MCInstrAnalysis class. This allows the targets to specify own versions of MCInstrDescs functions.
- Add overrides for ARM. - Teach llvm-objdump to use this instead of plain MCInstrDesc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137059 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/MC/MCInstrAnalysis.cpp20
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp53
2 files changed, 73 insertions, 0 deletions
diff --git a/lib/MC/MCInstrAnalysis.cpp b/lib/MC/MCInstrAnalysis.cpp
new file mode 100644
index 0000000000..03a35c597b
--- /dev/null
+++ b/lib/MC/MCInstrAnalysis.cpp
@@ -0,0 +1,20 @@
+//===-- MCInstrAnalysis.cpp - InstrDesc target hooks ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInstrAnalysis.h"
+using namespace llvm;
+
+uint64_t MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
+ uint64_t Size) const {
+ if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL)
+ return -1ULL;
+
+ int64_t Imm = Inst.getOperand(0).getImm();
+ return Addr+Size+Imm;
+}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index ffdf658728..0a4d671a4e 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -13,6 +13,7 @@
#include "ARMMCTargetDesc.h"
#include "ARMMCAsmInfo.h"
+#include "ARMBaseInfo.h"
#include "InstPrinter/ARMInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -159,6 +160,53 @@ static MCInstPrinter *createARMMCInstPrinter(const Target &T,
return 0;
}
+namespace {
+
+class ARMMCInstrAnalysis : public MCInstrAnalysis {
+public:
+ ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
+ virtual bool isBranch(const MCInst &Inst) const {
+ // Don't flag "bx lr" as a branch.
+ return MCInstrAnalysis::isBranch(Inst) && (Inst.getOpcode() != ARM::BX ||
+ Inst.getOperand(0).getReg() != ARM::LR);
+ }
+
+ virtual bool isUnconditionalBranch(const MCInst &Inst) const {
+ // BCCs with the "always" predicate are unconditional branches.
+ if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
+ return true;
+ return MCInstrAnalysis::isUnconditionalBranch(Inst);
+ }
+
+ virtual bool isConditionalBranch(const MCInst &Inst) const {
+ // BCCs with the "always" predicate are unconditional branches.
+ if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
+ return false;
+ return MCInstrAnalysis::isConditionalBranch(Inst);
+ }
+
+ virtual bool isReturn(const MCInst &Inst) const {
+ // Recognize "bx lr" as return.
+ return Inst.getOpcode() == ARM::BX && Inst.getOperand(0).getReg()==ARM::LR;
+ }
+
+ uint64_t evaluateBranch(const MCInst &Inst, uint64_t Addr,
+ uint64_t Size) const {
+ // We only handle PCRel branches for now.
+ if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
+ return -1ULL;
+
+ int64_t Imm = Inst.getOperand(0).getImm();
+ // FIXME: This is not right for thumb.
+ return Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
+ }
+};
+
+}
+
+static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
+ return new ARMMCInstrAnalysis(Info);
+}
// Force static initialization.
extern "C" void LLVMInitializeARMTargetMC() {
@@ -178,6 +226,11 @@ extern "C" void LLVMInitializeARMTargetMC() {
TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo);
TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo);
+ TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget,
+ createARMMCInstrAnalysis);
+ TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget,
+ createARMMCInstrAnalysis);
+
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget,
ARM_MC::createARMMCSubtargetInfo);