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