Thumb1RegisterInfo.cpp revision 77521f5232e679aa3de10aaaed2464aa91d7ff55
1b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin//===- Thumb1RegisterInfo.cpp - Thumb-1 Register Information -------*- C++ -*-===// 2a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 3a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// The LLVM Compiler Infrastructure 4a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 5a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// This file is distributed under the University of Illinois Open Source 6a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// License. See LICENSE.TXT for details. 7a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 8a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===// 9a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 10b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin// This file contains the Thumb-1 implementation of the TargetRegisterInfo class. 11a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov// 12a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov//===----------------------------------------------------------------------===// 13a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 14a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARM.h" 15a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMAddressingModes.h" 1677521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin#include "ARMBaseInstrInfo.h" 17a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMMachineFunctionInfo.h" 18a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "ARMSubtarget.h" 19b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1InstrInfo.h" 20b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin#include "Thumb1RegisterInfo.h" 21a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Constants.h" 22a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/DerivedTypes.h" 23a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineConstantPool.h" 24a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h" 25a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h" 26a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h" 27a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineLocation.h" 28a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h" 29a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetFrameInfo.h" 30a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Target/TargetMachine.h" 31a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/ADT/BitVector.h" 32a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/ADT/SmallVector.h" 33a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov#include "llvm/Support/CommandLine.h" 34ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h" 35a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovusing namespace llvm; 36a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 37a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic cl::opt<bool> 38a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikovThumbRegScavenging("enable-thumb-reg-scavenging", 39a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov cl::Hidden, 40a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov cl::desc("Enable register scavenging on Thumb")); 41a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 42db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid GoodwinThumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, 43b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const ARMSubtarget &sti) 44a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov : ARMBaseRegisterInfo(tii, sti) { 45a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 46a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 47a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitLoadConstPool - Emits a load from constpool to materialize the 48a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// specified immediate. 49b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, 50b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin MachineBasicBlock::iterator &MBBI, 5177521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin DebugLoc dl, 52b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin unsigned DestReg, int Val, 53db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid Goodwin ARMCC::CondCodes Pred, 54db5a71a8e01ed9a0d93a19176df6ea0aea510d7bDavid Goodwin unsigned PredReg) const { 55a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 56a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineConstantPool *ConstantPool = MF.getConstantPool(); 57a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Constant *C = ConstantInt::get(Type::Int32Ty, Val); 58a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 59a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 6077521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp), DestReg) 61a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addConstantPoolIndex(Idx); 62a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 63a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 64a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovconst TargetRegisterClass* 65b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid GoodwinThumb1RegisterInfo::getPhysicalRegisterRegClass(unsigned Reg, MVT VT) const { 6655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(Reg)) 67a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return ARM::tGPRRegisterClass; 68a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (Reg) { 69a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 70a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 71a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: 72a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R12: case ARM::SP: case ARM::LR: case ARM::PC: 73a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return ARM::GPRRegisterClass; 74a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 75a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 76a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return TargetRegisterInfo::getPhysicalRegisterRegClass(Reg, VT); 77a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 78a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 79a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovbool 80b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid GoodwinThumb1RegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { 81a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return ThumbRegScavenging; 82a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 83a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 84b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinbool Thumb1RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const { 85a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const MachineFrameInfo *FFI = MF.getFrameInfo(); 86a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned CFSize = FFI->getMaxCallFrameSize(); 87a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // It's not always a good idea to include the call frame as part of the 88a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // stack frame. ARM (especially Thumb) has small immediate offset to 89a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // address the stack frame. So a large call frame can cause poor codegen 90a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // and may even makes it impossible to scavenge a register. 91a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 92a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return false; 93a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 94a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return !MF.getFrameInfo()->hasVarSizedObjects(); 95a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 96a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 97a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize 98a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. Materialize the immediate 99a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// in a register using mov / mvn sequences or load the immediate from a 100a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constpool entry. 101a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 102a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, 103a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 104a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 105a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, bool CanChangeCC, 106a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 107b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 108a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 10955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov bool isHigh = !isARMLowRegister(DestReg) || 11055ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov (BaseReg != 0 && !isARMLowRegister(BaseReg)); 111a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = false; 112a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Subtract doesn't have high register version. Load the negative value 113a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // if either base or dest register is a high register. Also, if do not 114a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // issue sub as part of the sequence if condition register is to be 115a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // preserved. 116a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes < 0 && !isHigh && CanChangeCC) { 117a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isSub = true; 118a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = -NumBytes; 119a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 120a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned LdReg = DestReg; 121a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP) { 122a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(BaseReg == ARM::SP && "Unexpected!"); 123a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov LdReg = ARM::R3; 124a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVlor2hir), ARM::R12) 125a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(ARM::R3, RegState::Kill); 126a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 127a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 128a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes <= 255 && NumBytes >= 0) 129a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg).addImm(NumBytes); 130a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (NumBytes < 0 && NumBytes >= -255) { 131a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg).addImm(NumBytes); 132a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tNEG), LdReg) 133a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(LdReg, RegState::Kill); 134a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 13577521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, NumBytes); 136a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 137a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Emit add / sub. 138a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); 139a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, 140a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov TII.get(Opc), DestReg); 141a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP || isSub) 142a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); 143a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 144a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); 145a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == ARM::SP) 146a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVhir2lor), ARM::R3) 147a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(ARM::R12, RegState::Kill); 148a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 149a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 150a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// calcNumMI - Returns the number of instructions required to materialize 151a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// the specific add / sub r, c instruction. 152a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, 153a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits, unsigned Scale) { 154a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = 0; 155a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 156a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 157a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 158a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 159a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 160a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 161a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 162a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; // Followed by a number of tADDi8. 163a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 164a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 165a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 166a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs += Bytes / Chunk; 167a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((Bytes % Chunk) != 0) 168a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 169a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ExtraOpc) 170a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumMIs++; 171a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return NumMIs; 172a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 173a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 174a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize 175a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// a destreg = basereg + immediate in Thumb code. 176a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic 177a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovvoid emitThumbRegPlusImmediate(MachineBasicBlock &MBB, 178a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 179a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, unsigned BaseReg, 180a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes, const TargetInstrInfo &TII, 181b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 182a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 183a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = NumBytes < 0; 184a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (unsigned)NumBytes; 185a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Bytes = -NumBytes; 186a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isMul4 = (Bytes & 3) == 0; 187a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isTwoAddr = false; 188a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool DstNotEqBase = false; 189a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 1; 190a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 191a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Opc = 0; 192a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ExtraOpc = 0; 193a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 194a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg == BaseReg && BaseReg == ARM::SP) { 195a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); 196a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 7; 197a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 198a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; 199a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 200a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (!isSub && BaseReg == ARM::SP) { 201a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 403 202a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // => 203a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add sp, 100 * 4 204a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = add r1, 3 205a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isMul4) { 206a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes &= ~3; 207a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ExtraOpc = ARM::tADDi3; 208a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 209a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 210a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 211a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = ARM::tADDrSPi; 212a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 213a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // sp = sub sp, c 214a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r1 = sub sp, c 215a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r8 = sub sp, c 216a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DestReg != BaseReg) 217a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DstNotEqBase = true; 218a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 219a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 220a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 221a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 222a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 223a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); 224a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; 225a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > Threshold) { 226a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // This will expand into too many instructions. Load the immediate from a 227a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // constpool entry. 228a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, MBBI, DestReg, BaseReg, NumBytes, true, TII, 229a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MRI, dl); 230a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 231a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 232a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 233a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (DstNotEqBase) { 23455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { 235a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) 236a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = (1 << 3) - 1; 237a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 238a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 239a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl,TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3), DestReg) 240a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(BaseReg, RegState::Kill).addImm(ThisVal); 241a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 242a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) 243a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(BaseReg, RegState::Kill); 244a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 245a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 246a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 247a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 248a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Chunk = ((1 << NumBits) - 1) * Scale; 249a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (Bytes) { 250a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; 251a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Bytes -= ThisVal; 252a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ThisVal /= Scale; 253a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Build the new tADD / tSUB. 254a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isTwoAddr) 255a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) 256a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(DestReg).addImm(ThisVal); 257a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 258a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isKill = BaseReg != ARM::SP; 259a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) 260a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); 261a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BaseReg = DestReg; 262a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 263a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::tADDrSPi) { 264a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add sp, imm 265a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r4 = add r4, imm 266a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ... 267a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 268a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 1; 269a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Chunk = ((1 << NumBits) - 1) * Scale; 270a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; 271a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isTwoAddr = true; 272a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 273a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 274a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 275a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 276a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ExtraOpc) 277a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg) 278a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(DestReg, RegState::Kill) 279a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addImm(((unsigned)NumBytes) & 3); 280a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 281a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 28255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikovstatic void emitSPUpdate(MachineBasicBlock &MBB, 28355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MachineBasicBlock::iterator &MBBI, 28455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov const TargetInstrInfo &TII, DebugLoc dl, 285b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo &MRI, 28655ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov int NumBytes) { 287a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII, 28855ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov MRI, dl); 289a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 290a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 291b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo:: 292a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton KorobeynikoveliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 293a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator I) const { 294a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!hasReservedCallFrame(MF)) { 295a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we have alloca, convert as follows: 296a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKDOWN -> sub, sp, sp, amount 297a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // ADJCALLSTACKUP -> add, sp, sp, amount 298a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr *Old = I; 299a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = Old->getDebugLoc(); 300a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Amount = Old->getOperand(0).getImm(); 301a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Amount != 0) { 302a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // We need to keep the stack aligned properly. To do this, we round the 303a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // amount of space needed for the outgoing arguments up to the next 304a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // alignment boundary. 305a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); 306a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Amount = (Amount+Align-1)/Align*Align; 307a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 308a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the pseudo instruction with a new instruction... 309a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opc = Old->getOpcode(); 310a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 31155ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, -Amount); 312a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 313a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 31455ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, I, TII, dl, *this, Amount); 315a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 316a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 317a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 318a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(I); 319a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 320a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 321a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// emitThumbConstant - Emit a series of instructions to materialize a 322a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov/// constant. 323a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic void emitThumbConstant(MachineBasicBlock &MBB, 324a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator &MBBI, 325a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg, int Imm, 326a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrInfo &TII, 327b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin const Thumb1RegisterInfo& MRI, 328a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl) { 329a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isSub = Imm < 0; 330a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) Imm = -Imm; 331a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 332a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Chunk = (1 << 8) - 1; 333a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ThisVal = (Imm > Chunk) ? Chunk : Imm; 334a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Imm -= ThisVal; 335a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), DestReg).addImm(ThisVal); 336a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Imm > 0) 337a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, DestReg, DestReg, Imm, TII, MRI, dl); 338a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (isSub) 339a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tNEG), DestReg) 340a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(DestReg, RegState::Kill); 341a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 342a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 343b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 344b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin int SPAdj, RegScavenger *RS) const{ 345a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned i = 0; 346a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstr &MI = *II; 347a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = *MI.getParent(); 348a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFunction &MF = *MBB.getParent(); 349a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 350a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MI.getDebugLoc(); 351a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 352a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (!MI.getOperand(i).isFI()) { 353a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++i; 354a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 355a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 356a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 357a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned FrameReg = ARM::SP; 358a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FrameIndex = MI.getOperand(i).getIndex(); 359a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 360a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MF.getFrameInfo()->getStackSize() + SPAdj; 361a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 362a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex)) 363a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset -= AFI->getGPRCalleeSavedArea1Offset(); 364a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) 365a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset -= AFI->getGPRCalleeSavedArea2Offset(); 366a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else if (hasFP(MF)) { 367a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(SPAdj == 0 && "Unexpected"); 368a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // There is alloca()'s in this function, must reference off the frame 369a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // pointer instead. 370a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FrameReg = getFrameRegister(MF); 371a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset -= AFI->getFramePtrSpillOffset(); 372a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 373a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 374a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Opcode = MI.getOpcode(); 375a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const TargetInstrDesc &Desc = MI.getDesc(); 376a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); 377a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 378a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tADDrSPi) { 379a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += MI.getOperand(i+1).getImm(); 380a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 381a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Can't use tADDrSPi if it's based off the frame pointer. 382a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 383a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 384a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg != ARM::SP) { 385a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Opcode = ARM::tADDi3; 386a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDi3)); 387a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 3; 388a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 389a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 8; 390a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 391a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & 3) == 0 && 392a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Thumb add/sub sp, #imm immediate must be multiple of 4!"); 393a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 394a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 395a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset == 0) { 396a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Turn it into a move. 397a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tMOVhir2lor)); 398a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(FrameReg, false); 399a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.RemoveOperand(i+1); 400a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 401a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 402a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 403a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 404a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 405a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (((Offset / Scale) & ~Mask) == 0) { 406a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp / fp 407a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(FrameReg, false); 408a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i+1).ChangeToImmediate(Offset / Scale); 409a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 410a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 411a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 412a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DestReg = MI.getOperand(0).getReg(); 413a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Bytes = (Offset > 0) ? Offset : -Offset; 414a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); 415a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // MI would expand into a large number of instructions. Don't try to 416a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // simplify the immediate. 417a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumMIs > 2) { 418a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, DestReg, FrameReg, Offset, TII, 419a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 420a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(II); 421a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 422a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 423a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 424a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Offset > 0) { 425a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, imm to 426a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add sp, 255*4 427a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, (imm - 255*4) 428a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(FrameReg, false); 429a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i+1).ChangeToImmediate(Mask); 430a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset = (Offset - Mask * Scale); 431a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator NII = next(II); 432a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, NII, DestReg, DestReg, Offset, TII, 433a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 434a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 435a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Translate r0 = add sp, -imm to 436a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = -imm (this is then translated into a series of instructons) 437a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r0 = add r0, sp 438a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); 439a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tADDhirr)); 440a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(DestReg, false, false, true); 441a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i+1).ChangeToRegister(FrameReg, false); 442a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 443a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 444a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 445a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ImmIdx = 0; 446a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int InstrOffs = 0; 447a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBits = 0; 448a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Scale = 1; 449a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (AddrMode) { 450055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng case ARMII::AddrModeT1_s: { 451a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmIdx = i+1; 452a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov InstrOffs = MI.getOperand(ImmIdx).getImm(); 453a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = (FrameReg == ARM::SP) ? 8 : 5; 454a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Scale = 4; 455a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 456a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 457a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 458ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin LLVM_UNREACHABLE("Unsupported addressing mode!"); 459a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 460a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 461a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 462a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset += InstrOffs * Scale; 463a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); 464a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 465a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Common case: small offset, fits into instruction. 466a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineOperand &ImmOp = MI.getOperand(ImmIdx); 467a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int ImmedOffset = Offset / Scale; 468a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Mask = (1 << NumBits) - 1; 469a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if ((unsigned)Offset <= Mask * Scale) { 470a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Replace the FrameIndex with sp 471a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(FrameReg, false); 472a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 473a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 474a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 475a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 476a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill; 477055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng if (AddrMode == ARMII::AddrModeT1_s) { 478a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Thumb tLDRspi, tSTRspi. These will change to instructions that use 479a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // a different base register. 480a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBits = 5; 481a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Mask = (1 << NumBits) - 1; 482a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 483a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If this is a thumb spill / restore, we will be using a constpool load to 484a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // materialize the offset. 485055b0310f862b91f33699037ce67d3ab8137c20cEvan Cheng if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore) 486a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(0); 487a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 488a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Otherwise, it didn't fit. Pull in what we can to simplify the immed. 489a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmedOffset = ImmedOffset & Mask; 490a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ImmOp.ChangeToImmediate(ImmedOffset); 491a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset &= ~(Mask*Scale); 492a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 493a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 494a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 495a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // If we get here, the immediate doesn't fit into the instruction. We folded 496a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // as much as possible above, handle the rest, providing a register that is 497a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // SP+LargeImm. 498a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(Offset && "This code isn't needed if offset already handled!"); 499a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 500a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Desc.mayLoad()) { 501a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use the destination register to materialize sp + offset. 502a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = MI.getOperand(0).getReg(); 503a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 504a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tRestore) { 505a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 506a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg, 507a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset, false, TII, *this, dl); 508a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 50977521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin emitLoadConstPool(MBB, II, dl, TmpReg, Offset); 510a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 511a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 512a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 513a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII, 514a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 515a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tLDR)); 516a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); 517a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) 518a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use [reg, reg] addrmode. 519a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); 520a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else // tLDR has an extra register operand. 521a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(0, false)); 522a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else if (Desc.mayStore()) { 523a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // FIXME! This is horrific!!! We need register scavenging. 524a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Our temporary workaround has marked r3 unavailable. Of course, r3 is 525a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // also a ABI register so it's possible that is is the register that is 526a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // being storing here. If that's the case, we do the following: 527a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r12 = r2 528a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Use r2 to materialize sp + offset 529a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // str r3, r2 530a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // r2 = r12 531a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned ValReg = MI.getOperand(0).getReg(); 532a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned TmpReg = ARM::R3; 533a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov bool UseRR = false; 534a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ValReg == ARM::R3) { 535a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, II, dl, TII.get(ARM::tMOVlor2hir), ARM::R12) 536a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(ARM::R2, RegState::Kill); 537a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov TmpReg = ARM::R2; 538a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 539a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (TmpReg == ARM::R3 && AFI->isR3LiveIn()) 540a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, II, dl, TII.get(ARM::tMOVlor2hir), ARM::R12) 541a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(ARM::R3, RegState::Kill); 542a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Opcode == ARM::tSpill) { 543a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (FrameReg == ARM::SP) 544a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg, 545a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov Offset, false, TII, *this, dl); 546a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else { 54777521f5232e679aa3de10aaaed2464aa91d7ff55David Goodwin emitLoadConstPool(MBB, II, dl, TmpReg, Offset); 548a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov UseRR = true; 549a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 550a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 551a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII, 552a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov *this, dl); 553a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.setDesc(TII.get(ARM::tSTR)); 554a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); 555a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (UseRR) // Use [reg, reg] addrmode. 556a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); 557a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else // tSTR has an extra register operand. 558a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI.addOperand(MachineOperand::CreateReg(0, false)); 559a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 560a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator NII = next(II); 561a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (ValReg == ARM::R3) 562a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, NII, dl, TII.get(ARM::tMOVhir2lor), ARM::R2) 563a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(ARM::R12, RegState::Kill); 564a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (TmpReg == ARM::R3 && AFI->isR3LiveIn()) 565a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, NII, dl, TII.get(ARM::tMOVhir2lor), ARM::R3) 566a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(ARM::R12, RegState::Kill); 567a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 568a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert(false && "Unexpected opcode!"); 569a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 570a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 571b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const { 572a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock &MBB = MF.front(); 573a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator MBBI = MBB.begin(); 574a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFrameInfo *MFI = MF.getFrameInfo(); 575a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 576a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 577a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned NumBytes = MFI->getStackSize(); 578a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 579a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = (MBBI != MBB.end() ? 580a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); 581a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 582a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Check if R3 is live in. It might have to be used as a scratch register. 583a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (MachineRegisterInfo::livein_iterator I =MF.getRegInfo().livein_begin(), 584a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov E = MF.getRegInfo().livein_end(); I != E; ++I) { 585a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (I->first == ARM::R3) { 586a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setR3IsLiveIn(true); 587a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 588a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 589a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 590a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 591a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. 592a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = (NumBytes + 3) & ~3; 593a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MFI->setStackSize(NumBytes); 594a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 595a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Determine the sizes of each callee-save spill areas and record which frame 596a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // belongs to which callee-save spill areas. 597a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 598a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FramePtrSpillFI = 0; 599a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 600a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (VARegSaveSize) 60155ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -VARegSaveSize); 602a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 603a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!AFI->hasStackFrame()) { 604a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes != 0) 60555ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); 606a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return; 607a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 608a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 609a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 610a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned Reg = CSI[i].getReg(); 611a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int FI = CSI[i].getFrameIdx(); 612a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov switch (Reg) { 613a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R4: 614a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R5: 615a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R6: 616a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R7: 617a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::LR: 618a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == FramePtr) 619a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FramePtrSpillFI = FI; 620a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea1Frame(FI); 621a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS1Size += 4; 622a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 623a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R8: 624a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R9: 625a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R10: 626a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov case ARM::R11: 627a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == FramePtr) 628a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov FramePtrSpillFI = FI; 629a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetDarwin()) { 630a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea2Frame(FI); 631a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS2Size += 4; 632a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 633a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addGPRCalleeSavedArea1Frame(FI); 634a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov GPRCS1Size += 4; 635a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 636a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov break; 637a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov default: 638a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->addDPRCalleeSavedAreaFrame(FI); 639a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DPRCSSize += 8; 640a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 641a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 642a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 643a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 644a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++MBBI; 645a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.end()) 646a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov dl = MBBI->getDebugLoc(); 647a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 648a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 649a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Darwin ABI requires FP to point to the stack slot that contains the 650a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // previous FP. 651a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetDarwin() || hasFP(MF)) { 652a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineInstrBuilder MIB = 653a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) 654a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addFrameIndex(FramePtrSpillFI).addImm(0); 655a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 656a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 657a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Determine starting offsets of spill areas. 658a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); 659a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; 660a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; 661a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); 662a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 663a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 664a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 665a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 666a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = DPRCSOffset; 667a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes) { 668a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Insert it after all the callee-save spills. 66955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); 670a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 671a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 672a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (STI.isTargetELF() && hasFP(MF)) { 673a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - 674a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getFramePtrSpillOffset()); 675a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 676a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 677a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 678a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 679a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 680a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 681a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 682a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { 683a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov for (unsigned i = 0; CSRegs[i]; ++i) 684a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (Reg == CSRegs[i]) 685a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return true; 686a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return false; 687a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 688a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 689a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikovstatic bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { 690a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov return (MI->getOpcode() == ARM::tRestore && 691a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MI->getOperand(1).isFI() && 692a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)); 693a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 694a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 695b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwinvoid Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, 696b50ea5c48f8b1ce259e034ca5c16dc14af1a582cDavid Goodwin MachineBasicBlock &MBB) const { 697a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator MBBI = prior(MBB.end()); 698a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov assert((MBBI->getOpcode() == ARM::tBX_RET || 699a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBBI->getOpcode() == ARM::tPOP_RET) && 700a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov "Can only insert epilog into returning blocks"); 701a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov DebugLoc dl = MBBI->getDebugLoc(); 702a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineFrameInfo *MFI = MF.getFrameInfo(); 703a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 704a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); 705a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov int NumBytes = (int)MFI->getStackSize(); 706a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 707a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!AFI->hasStackFrame()) { 708a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes != 0) 70955ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); 710a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 711a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Unwind MBBI to point to first LDR / FLDD. 712a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov const unsigned *CSRegs = getCalleeSavedRegs(); 713a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI != MBB.begin()) { 714a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov do 715a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov --MBBI; 716a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs)); 717a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (!isCSRestore(MBBI, CSRegs)) 718a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov ++MBBI; 719a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 720a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 721a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Move SP to start of FP callee save spill area. 722a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + 723a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getGPRCalleeSavedArea2Size() + 724a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov AFI->getDPRCalleeSavedAreaSize()); 725a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 726a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (hasFP(MF)) { 727a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 728a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Reset SP based on frame pointer only if the stack frame extends beyond 729a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // frame pointer stack slot or target is ELF and the function has FP. 730a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (NumBytes) 731a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes, 732a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov TII, *this, dl); 733a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov else 734a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVlor2hir), ARM::SP) 735a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov .addReg(FramePtr); 736a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else { 737a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (MBBI->getOpcode() == ARM::tBX_RET && 738a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov &MBB.front() != MBBI && 739a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov prior(MBBI)->getOpcode() == ARM::tPOP) { 740a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MachineBasicBlock::iterator PMBBI = prior(MBBI); 74155ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, PMBBI, TII, dl, *this, NumBytes); 742a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } else 74355ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); 744a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 745a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 746a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 747a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov if (VARegSaveSize) { 748a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // Epilogue for vararg functions: pop LR to R3 and branch off it. 749a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov // FIXME: Verify this is still ok when R3 is no longer being reserved. 750a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)).addReg(ARM::R3); 751a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 75255ad1f22b4554be3a9547fe7a8d84ce05b3d5c72Anton Korobeynikov emitSPUpdate(MBB, MBBI, TII, dl, *this, VARegSaveSize); 753a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov 754a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)).addReg(ARM::R3); 755a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov MBB.erase(MBBI); 756a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov } 757a98cbc554ca2cd40426e7c3ff8d1467da32e195dAnton Korobeynikov} 758