10b57cec5SDimitry Andric //===-- SparcRegisterInfo.cpp - SPARC Register Information ----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the SPARC implementation of the TargetRegisterInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "SparcRegisterInfo.h" 140b57cec5SDimitry Andric #include "Sparc.h" 150b57cec5SDimitry Andric #include "SparcSubtarget.h" 160b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 210b57cec5SDimitry Andric #include "llvm/IR/Type.h" 220b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC 280b57cec5SDimitry Andric #include "SparcGenRegisterInfo.inc" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric static cl::opt<bool> 310b57cec5SDimitry Andric ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden, cl::init(false), 320b57cec5SDimitry Andric cl::desc("Reserve application registers (%g2-%g4)")); 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric SparcRegisterInfo::SparcRegisterInfo() : SparcGenRegisterInfo(SP::O7) {} 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric const MCPhysReg* 370b57cec5SDimitry Andric SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 380b57cec5SDimitry Andric return CSR_SaveList; 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric const uint32_t * 420b57cec5SDimitry Andric SparcRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 430b57cec5SDimitry Andric CallingConv::ID CC) const { 440b57cec5SDimitry Andric return CSR_RegMask; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric const uint32_t* 480b57cec5SDimitry Andric SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const { 490b57cec5SDimitry Andric return RTCSR_RegMask; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 530b57cec5SDimitry Andric BitVector Reserved(getNumRegs()); 540b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 550b57cec5SDimitry Andric // FIXME: G1 reserved for now for large imm generation by frame code. 560b57cec5SDimitry Andric Reserved.set(SP::G1); 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // G1-G4 can be used in applications. 590b57cec5SDimitry Andric if (ReserveAppRegisters) { 600b57cec5SDimitry Andric Reserved.set(SP::G2); 610b57cec5SDimitry Andric Reserved.set(SP::G3); 620b57cec5SDimitry Andric Reserved.set(SP::G4); 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric // G5 is not reserved in 64 bit mode. 650b57cec5SDimitry Andric if (!Subtarget.is64Bit()) 660b57cec5SDimitry Andric Reserved.set(SP::G5); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric Reserved.set(SP::O6); 690b57cec5SDimitry Andric Reserved.set(SP::I6); 700b57cec5SDimitry Andric Reserved.set(SP::I7); 710b57cec5SDimitry Andric Reserved.set(SP::G0); 720b57cec5SDimitry Andric Reserved.set(SP::G6); 730b57cec5SDimitry Andric Reserved.set(SP::G7); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Also reserve the register pair aliases covering the above 760b57cec5SDimitry Andric // registers, with the same conditions. 770b57cec5SDimitry Andric Reserved.set(SP::G0_G1); 780b57cec5SDimitry Andric if (ReserveAppRegisters) 790b57cec5SDimitry Andric Reserved.set(SP::G2_G3); 800b57cec5SDimitry Andric if (ReserveAppRegisters || !Subtarget.is64Bit()) 810b57cec5SDimitry Andric Reserved.set(SP::G4_G5); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric Reserved.set(SP::O6_O7); 840b57cec5SDimitry Andric Reserved.set(SP::I6_I7); 850b57cec5SDimitry Andric Reserved.set(SP::G6_G7); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Unaliased double registers are not available in non-V9 targets. 880b57cec5SDimitry Andric if (!Subtarget.isV9()) { 890b57cec5SDimitry Andric for (unsigned n = 0; n != 16; ++n) { 900b57cec5SDimitry Andric for (MCRegAliasIterator AI(SP::D16 + n, this, true); AI.isValid(); ++AI) 910b57cec5SDimitry Andric Reserved.set(*AI); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // Reserve ASR1-ASR31 960b57cec5SDimitry Andric for (unsigned n = 0; n < 31; n++) 970b57cec5SDimitry Andric Reserved.set(SP::ASR1 + n); 980b57cec5SDimitry Andric 99*74626c16SDimitry Andric for (TargetRegisterClass::iterator i = SP::IntRegsRegClass.begin(); 100*74626c16SDimitry Andric i != SP::IntRegsRegClass.end(); ++i) { 101*74626c16SDimitry Andric if (MF.getSubtarget<SparcSubtarget>().isRegisterReserved(*i)) 102*74626c16SDimitry Andric markSuperRegs(Reserved, *i); 103*74626c16SDimitry Andric } 104*74626c16SDimitry Andric 105*74626c16SDimitry Andric assert(checkAllSuperRegsMarked(Reserved)); 1060b57cec5SDimitry Andric return Reserved; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 109*74626c16SDimitry Andric bool SparcRegisterInfo::isReservedReg(const MachineFunction &MF, 110*74626c16SDimitry Andric MCRegister Reg) const { 111*74626c16SDimitry Andric return getReservedRegs(MF)[Reg]; 112*74626c16SDimitry Andric } 113*74626c16SDimitry Andric 1140b57cec5SDimitry Andric const TargetRegisterClass* 1150b57cec5SDimitry Andric SparcRegisterInfo::getPointerRegClass(const MachineFunction &MF, 1160b57cec5SDimitry Andric unsigned Kind) const { 1170b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 1180b57cec5SDimitry Andric return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II, 1220b57cec5SDimitry Andric MachineInstr &MI, const DebugLoc &dl, 1230b57cec5SDimitry Andric unsigned FIOperandNum, int Offset, unsigned FramePtr) { 1240b57cec5SDimitry Andric // Replace frame index with a frame pointer reference. 1250b57cec5SDimitry Andric if (Offset >= -4096 && Offset <= 4095) { 1260b57cec5SDimitry Andric // If the offset is small enough to fit in the immediate field, directly 1270b57cec5SDimitry Andric // encode it. 1280b57cec5SDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false); 1290b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 1300b57cec5SDimitry Andric return; 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric // FIXME: it would be better to scavenge a register here instead of 1360b57cec5SDimitry Andric // reserving G1 all of the time. 1370b57cec5SDimitry Andric if (Offset >= 0) { 1380b57cec5SDimitry Andric // Emit nonnegaive immediates with sethi + or. 1390b57cec5SDimitry Andric // sethi %hi(Offset), %g1 1400b57cec5SDimitry Andric // add %g1, %fp, %g1 1410b57cec5SDimitry Andric // Insert G1+%lo(offset) into the user. 1420b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1) 1430b57cec5SDimitry Andric .addImm(HI22(Offset)); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // Emit G1 = G1 + I6 1470b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1) 1480b57cec5SDimitry Andric .addReg(FramePtr); 1490b57cec5SDimitry Andric // Insert: G1+%lo(offset) into the user. 1500b57cec5SDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false); 1510b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset)); 1520b57cec5SDimitry Andric return; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric // Emit Negative numbers with sethi + xor 1560b57cec5SDimitry Andric // sethi %hix(Offset), %g1 1570b57cec5SDimitry Andric // xor %g1, %lox(offset), %g1 1580b57cec5SDimitry Andric // add %g1, %fp, %g1 1590b57cec5SDimitry Andric // Insert: G1 + 0 into the user. 1600b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1) 1610b57cec5SDimitry Andric .addImm(HIX22(Offset)); 1620b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1) 1630b57cec5SDimitry Andric .addReg(SP::G1).addImm(LOX10(Offset)); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1) 1660b57cec5SDimitry Andric .addReg(FramePtr); 1670b57cec5SDimitry Andric // Insert: G1+%lo(offset) into the user. 1680b57cec5SDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false); 1690b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric 173bdd1243dSDimitry Andric bool 1740b57cec5SDimitry Andric SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 1750b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum, 1760b57cec5SDimitry Andric RegScavenger *RS) const { 1770b57cec5SDimitry Andric assert(SPAdj == 0 && "Unexpected"); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric MachineInstr &MI = *II; 1800b57cec5SDimitry Andric DebugLoc dl = MI.getDebugLoc(); 1810b57cec5SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 1820b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 1830b57cec5SDimitry Andric const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); 1840b57cec5SDimitry Andric const SparcFrameLowering *TFI = getFrameLowering(MF); 1850b57cec5SDimitry Andric 1865ffd83dbSDimitry Andric Register FrameReg; 1870b57cec5SDimitry Andric int Offset; 188e8d8bef9SDimitry Andric Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed(); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric Offset += MI.getOperand(FIOperandNum + 1).getImm(); 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) { 1930b57cec5SDimitry Andric if (MI.getOpcode() == SP::STQFri) { 1940b57cec5SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 1958bcb0991SDimitry Andric Register SrcReg = MI.getOperand(2).getReg(); 1968bcb0991SDimitry Andric Register SrcEvenReg = getSubReg(SrcReg, SP::sub_even64); 1978bcb0991SDimitry Andric Register SrcOddReg = getSubReg(SrcReg, SP::sub_odd64); 1980b57cec5SDimitry Andric MachineInstr *StMI = 1990b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri)) 2000b57cec5SDimitry Andric .addReg(FrameReg).addImm(0).addReg(SrcEvenReg); 2010b57cec5SDimitry Andric replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg); 2020b57cec5SDimitry Andric MI.setDesc(TII.get(SP::STDFri)); 2030b57cec5SDimitry Andric MI.getOperand(2).setReg(SrcOddReg); 2040b57cec5SDimitry Andric Offset += 8; 2050b57cec5SDimitry Andric } else if (MI.getOpcode() == SP::LDQFri) { 2060b57cec5SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 2078bcb0991SDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 2088bcb0991SDimitry Andric Register DestEvenReg = getSubReg(DestReg, SP::sub_even64); 2098bcb0991SDimitry Andric Register DestOddReg = getSubReg(DestReg, SP::sub_odd64); 2100b57cec5SDimitry Andric MachineInstr *LdMI = 2110b57cec5SDimitry Andric BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg) 2120b57cec5SDimitry Andric .addReg(FrameReg).addImm(0); 2130b57cec5SDimitry Andric replaceFI(MF, *LdMI, *LdMI, dl, 1, Offset, FrameReg); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric MI.setDesc(TII.get(SP::LDDFri)); 2160b57cec5SDimitry Andric MI.getOperand(0).setReg(DestOddReg); 2170b57cec5SDimitry Andric Offset += 8; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg); 222bdd1243dSDimitry Andric // replaceFI never removes II 223bdd1243dSDimitry Andric return false; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 2270b57cec5SDimitry Andric return SP::I6; 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // Sparc has no architectural need for stack realignment support, 2310b57cec5SDimitry Andric // except that LLVM unfortunately currently implements overaligned 2320b57cec5SDimitry Andric // stack objects by depending upon stack realignment support. 2330b57cec5SDimitry Andric // If that ever changes, this can probably be deleted. 2340b57cec5SDimitry Andric bool SparcRegisterInfo::canRealignStack(const MachineFunction &MF) const { 2350b57cec5SDimitry Andric if (!TargetRegisterInfo::canRealignStack(MF)) 2360b57cec5SDimitry Andric return false; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric // Sparc always has a fixed frame pointer register, so don't need to 2390b57cec5SDimitry Andric // worry about needing to reserve it. [even if we don't have a frame 2400b57cec5SDimitry Andric // pointer for our frame, it still cannot be used for other things, 2410b57cec5SDimitry Andric // or register window traps will be SADNESS.] 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // If there's a reserved call frame, we can use SP to access locals. 2440b57cec5SDimitry Andric if (getFrameLowering(MF)->hasReservedCallFrame(MF)) 2450b57cec5SDimitry Andric return true; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // Otherwise, we'd need a base pointer, but those aren't implemented 2480b57cec5SDimitry Andric // for SPARC at the moment. 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric return false; 2510b57cec5SDimitry Andric } 252