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/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/IR/Function.h" 27 #include "llvm/IR/GlobalVariable.h" 28 #include "llvm/MC/MCAsmInfo.h" 29 #include "llvm/MC/MCInst.h" 30 using namespace llvm; 31 32 ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) 33 : ARMBaseInstrInfo(STI), RI() {} 34 35 /// Return the noop instruction to use for a noop. 36 void ARMInstrInfo::getNoop(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 52 unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { 53 switch (Opc) { 54 default: 55 break; 56 case ARM::LDR_PRE_IMM: 57 case ARM::LDR_PRE_REG: 58 case ARM::LDR_POST_IMM: 59 case ARM::LDR_POST_REG: 60 return ARM::LDRi12; 61 case ARM::LDRH_PRE: 62 case ARM::LDRH_POST: 63 return ARM::LDRH; 64 case ARM::LDRB_PRE_IMM: 65 case ARM::LDRB_PRE_REG: 66 case ARM::LDRB_POST_IMM: 67 case ARM::LDRB_POST_REG: 68 return ARM::LDRBi12; 69 case ARM::LDRSH_PRE: 70 case ARM::LDRSH_POST: 71 return ARM::LDRSH; 72 case ARM::LDRSB_PRE: 73 case ARM::LDRSB_POST: 74 return ARM::LDRSB; 75 case ARM::STR_PRE_IMM: 76 case ARM::STR_PRE_REG: 77 case ARM::STR_POST_IMM: 78 case ARM::STR_POST_REG: 79 return ARM::STRi12; 80 case ARM::STRH_PRE: 81 case ARM::STRH_POST: 82 return ARM::STRH; 83 case ARM::STRB_PRE_IMM: 84 case ARM::STRB_PRE_REG: 85 case ARM::STRB_POST_IMM: 86 case ARM::STRB_POST_REG: 87 return ARM::STRBi12; 88 } 89 90 return 0; 91 } 92 93 void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const { 94 MachineFunction &MF = *MI->getParent()->getParent(); 95 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>(); 96 const TargetMachine &TM = MF.getTarget(); 97 98 if (!Subtarget.useMovt(MF)) { 99 if (TM.isPositionIndependent()) 100 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12); 101 else 102 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12); 103 return; 104 } 105 106 if (!TM.isPositionIndependent()) { 107 expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12); 108 return; 109 } 110 111 const GlobalValue *GV = 112 cast<GlobalValue>((*MI->memoperands_begin())->getValue()); 113 114 if (!Subtarget.isGVIndirectSymbol(GV)) { 115 expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12); 116 return; 117 } 118 119 MachineBasicBlock &MBB = *MI->getParent(); 120 DebugLoc DL = MI->getDebugLoc(); 121 unsigned Reg = MI->getOperand(0).getReg(); 122 MachineInstrBuilder MIB; 123 124 MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg) 125 .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY); 126 auto Flags = MachineMemOperand::MOLoad | 127 MachineMemOperand::MODereferenceable | 128 MachineMemOperand::MOInvariant; 129 MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( 130 MachinePointerInfo::getGOT(*MBB.getParent()), Flags, 4, 4); 131 MIB.addMemOperand(MMO); 132 BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg) 133 .addReg(Reg, RegState::Kill) 134 .addImm(0) 135 .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()) 136 .add(predOps(ARMCC::AL)); 137 } 138 139 std::pair<unsigned, unsigned> 140 ARMInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 141 const unsigned Mask = ARMII::MO_OPTION_MASK; 142 return std::make_pair(TF & Mask, TF & ~Mask); 143 } 144 145 ArrayRef<std::pair<unsigned, const char *>> 146 ARMInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 147 using namespace ARMII; 148 149 static const std::pair<unsigned, const char *> TargetFlags[] = { 150 {MO_LO16, "arm-lo16"}, {MO_HI16, "arm-hi16"}}; 151 return makeArrayRef(TargetFlags); 152 } 153 154 ArrayRef<std::pair<unsigned, const char *>> 155 ARMInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { 156 using namespace ARMII; 157 158 static const std::pair<unsigned, const char *> TargetFlags[] = { 159 {MO_GOT, "arm-got"}, 160 {MO_SBREL, "arm-sbrel"}, 161 {MO_DLLIMPORT, "arm-dllimport"}, 162 {MO_SECREL, "arm-secrel"}, 163 {MO_NONLAZY, "arm-nonlazy"}}; 164 return makeArrayRef(TargetFlags); 165 } 166