1//===-- ARMInstrInfo.cpp - ARM Instruction Information --------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the ARM implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARMInstrInfo.h"
15#include "ARM.h"
16#include "ARMConstantPoolValue.h"
17#include "ARMMachineFunctionInfo.h"
18#include "ARMTargetMachine.h"
19#include "MCTargetDesc/ARMAddressingModes.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/CodeGen/LiveVariables.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineJumpTableInfo.h"
25#include "llvm/Function.h"
26#include "llvm/GlobalVariable.h"
27#include "llvm/MC/MCAsmInfo.h"
28#include "llvm/MC/MCInst.h"
29using namespace llvm;
30
31ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
32  : ARMBaseInstrInfo(STI), RI(*this, STI) {
33}
34
35/// getNoopForMachoTarget - Return the noop instruction to use for a noop.
36void ARMInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const {
37  if (hasNOP()) {
38    NopInst.setOpcode(ARM::HINT);
39    NopInst.addOperand(MCOperand::CreateImm(0));
40    NopInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
41    NopInst.addOperand(MCOperand::CreateReg(0));
42  } else {
43    NopInst.setOpcode(ARM::MOVr);
44    NopInst.addOperand(MCOperand::CreateReg(ARM::R0));
45    NopInst.addOperand(MCOperand::CreateReg(ARM::R0));
46    NopInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
47    NopInst.addOperand(MCOperand::CreateReg(0));
48    NopInst.addOperand(MCOperand::CreateReg(0));
49  }
50}
51
52unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
53  switch (Opc) {
54  default: break;
55  case ARM::LDR_PRE_IMM:
56  case ARM::LDR_PRE_REG:
57  case ARM::LDR_POST_IMM:
58  case ARM::LDR_POST_REG:
59    return ARM::LDRi12;
60  case ARM::LDRH_PRE:
61  case ARM::LDRH_POST:
62    return ARM::LDRH;
63  case ARM::LDRB_PRE_IMM:
64  case ARM::LDRB_PRE_REG:
65  case ARM::LDRB_POST_IMM:
66  case ARM::LDRB_POST_REG:
67    return ARM::LDRBi12;
68  case ARM::LDRSH_PRE:
69  case ARM::LDRSH_POST:
70    return ARM::LDRSH;
71  case ARM::LDRSB_PRE:
72  case ARM::LDRSB_POST:
73    return ARM::LDRSB;
74  case ARM::STR_PRE_IMM:
75  case ARM::STR_PRE_REG:
76  case ARM::STR_POST_IMM:
77  case ARM::STR_POST_REG:
78    return ARM::STRi12;
79  case ARM::STRH_PRE:
80  case ARM::STRH_POST:
81    return ARM::STRH;
82  case ARM::STRB_PRE_IMM:
83  case ARM::STRB_PRE_REG:
84  case ARM::STRB_POST_IMM:
85  case ARM::STRB_POST_REG:
86    return ARM::STRBi12;
87  }
88
89  return 0;
90}
91
92namespace {
93  /// ARMCGBR - Create Global Base Reg pass. This initializes the PIC
94  /// global base register for ARM ELF.
95  struct ARMCGBR : public MachineFunctionPass {
96    static char ID;
97    ARMCGBR() : MachineFunctionPass(ID) {}
98
99    virtual bool runOnMachineFunction(MachineFunction &MF) {
100      ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
101      if (AFI->getGlobalBaseReg() == 0)
102        return false;
103
104      const ARMTargetMachine *TM =
105        static_cast<const ARMTargetMachine *>(&MF.getTarget());
106      if (TM->getRelocationModel() != Reloc::PIC_)
107        return false;
108
109      LLVMContext* Context = &MF.getFunction()->getContext();
110      GlobalValue *GV = new GlobalVariable(Type::getInt32Ty(*Context), false,
111                                           GlobalValue::ExternalLinkage, 0,
112                                           "_GLOBAL_OFFSET_TABLE_");
113      unsigned Id = AFI->createPICLabelUId();
114      ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id);
115      unsigned Align = TM->getTargetData()->getPrefTypeAlignment(GV->getType());
116      unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align);
117
118      MachineBasicBlock &FirstMBB = MF.front();
119      MachineBasicBlock::iterator MBBI = FirstMBB.begin();
120      DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
121      unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
122      unsigned Opc = TM->getSubtarget<ARMSubtarget>().isThumb2() ?
123                     ARM::t2LDRpci : ARM::LDRcp;
124      const TargetInstrInfo &TII = *TM->getInstrInfo();
125      MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL,
126                                        TII.get(Opc), GlobalBaseReg)
127                                .addConstantPoolIndex(Idx);
128      if (Opc == ARM::LDRcp)
129        MIB.addImm(0);
130      AddDefaultPred(MIB);
131
132      return true;
133    }
134
135    virtual const char *getPassName() const {
136      return "ARM PIC Global Base Reg Initialization";
137    }
138
139    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
140      AU.setPreservesCFG();
141      MachineFunctionPass::getAnalysisUsage(AU);
142    }
143  };
144}
145
146char ARMCGBR::ID = 0;
147FunctionPass*
148llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); }
149