xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430RegisterInfo.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- MSP430RegisterInfo.cpp - MSP430 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 MSP430 implementation of the TargetRegisterInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MSP430RegisterInfo.h"
140b57cec5SDimitry Andric #include "MSP430.h"
150b57cec5SDimitry Andric #include "MSP430MachineFunctionInfo.h"
160b57cec5SDimitry Andric #include "MSP430TargetMachine.h"
170b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
210b57cec5SDimitry Andric #include "llvm/IR/Function.h"
220b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
230b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
240b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define DEBUG_TYPE "msp430-reg-info"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
310b57cec5SDimitry Andric #include "MSP430GenRegisterInfo.inc"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric // FIXME: Provide proper call frame setup / destroy opcodes.
MSP430RegisterInfo()340b57cec5SDimitry Andric MSP430RegisterInfo::MSP430RegisterInfo()
350b57cec5SDimitry Andric   : MSP430GenRegisterInfo(MSP430::PC) {}
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric const MCPhysReg*
getCalleeSavedRegs(const MachineFunction * MF) const380b57cec5SDimitry Andric MSP430RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
390b57cec5SDimitry Andric   const MSP430FrameLowering *TFI = getFrameLowering(*MF);
400b57cec5SDimitry Andric   const Function* F = &MF->getFunction();
410b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegs[] = {
425ffd83dbSDimitry Andric     MSP430::R4, MSP430::R5, MSP430::R6, MSP430::R7,
430b57cec5SDimitry Andric     MSP430::R8, MSP430::R9, MSP430::R10,
440b57cec5SDimitry Andric     0
450b57cec5SDimitry Andric   };
460b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegsFP[] = {
470b57cec5SDimitry Andric     MSP430::R5, MSP430::R6, MSP430::R7,
480b57cec5SDimitry Andric     MSP430::R8, MSP430::R9, MSP430::R10,
490b57cec5SDimitry Andric     0
500b57cec5SDimitry Andric   };
510b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegsIntr[] = {
525ffd83dbSDimitry Andric     MSP430::R4,  MSP430::R5,  MSP430::R6,  MSP430::R7,
530b57cec5SDimitry Andric     MSP430::R8,  MSP430::R9,  MSP430::R10, MSP430::R11,
540b57cec5SDimitry Andric     MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15,
550b57cec5SDimitry Andric     0
560b57cec5SDimitry Andric   };
570b57cec5SDimitry Andric   static const MCPhysReg CalleeSavedRegsIntrFP[] = {
580b57cec5SDimitry Andric     MSP430::R5,  MSP430::R6,  MSP430::R7,
590b57cec5SDimitry Andric     MSP430::R8,  MSP430::R9,  MSP430::R10, MSP430::R11,
600b57cec5SDimitry Andric     MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15,
610b57cec5SDimitry Andric     0
620b57cec5SDimitry Andric   };
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   if (TFI->hasFP(*MF))
650b57cec5SDimitry Andric     return (F->getCallingConv() == CallingConv::MSP430_INTR ?
660b57cec5SDimitry Andric             CalleeSavedRegsIntrFP : CalleeSavedRegsFP);
670b57cec5SDimitry Andric   else
680b57cec5SDimitry Andric     return (F->getCallingConv() == CallingConv::MSP430_INTR ?
690b57cec5SDimitry Andric             CalleeSavedRegsIntr : CalleeSavedRegs);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
getReservedRegs(const MachineFunction & MF) const730b57cec5SDimitry Andric BitVector MSP430RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
740b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
750b57cec5SDimitry Andric   const MSP430FrameLowering *TFI = getFrameLowering(MF);
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   // Mark 4 special registers with subregisters as reserved.
780b57cec5SDimitry Andric   Reserved.set(MSP430::PCB);
790b57cec5SDimitry Andric   Reserved.set(MSP430::SPB);
800b57cec5SDimitry Andric   Reserved.set(MSP430::SRB);
810b57cec5SDimitry Andric   Reserved.set(MSP430::CGB);
820b57cec5SDimitry Andric   Reserved.set(MSP430::PC);
830b57cec5SDimitry Andric   Reserved.set(MSP430::SP);
840b57cec5SDimitry Andric   Reserved.set(MSP430::SR);
850b57cec5SDimitry Andric   Reserved.set(MSP430::CG);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   // Mark frame pointer as reserved if needed.
880b57cec5SDimitry Andric   if (TFI->hasFP(MF)) {
895ffd83dbSDimitry Andric     Reserved.set(MSP430::R4B);
905ffd83dbSDimitry Andric     Reserved.set(MSP430::R4);
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   return Reserved;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const970b57cec5SDimitry Andric MSP430RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind)
980b57cec5SDimitry Andric                                                                          const {
990b57cec5SDimitry Andric   return &MSP430::GR16RegClass;
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
102bdd1243dSDimitry Andric bool
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const1030b57cec5SDimitry Andric MSP430RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
1040b57cec5SDimitry Andric                                         int SPAdj, unsigned FIOperandNum,
1050b57cec5SDimitry Andric                                         RegScavenger *RS) const {
1060b57cec5SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   MachineInstr &MI = *II;
1090b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
1100b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
1110b57cec5SDimitry Andric   const MSP430FrameLowering *TFI = getFrameLowering(MF);
1120b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
1130b57cec5SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
1140b57cec5SDimitry Andric 
1155ffd83dbSDimitry Andric   unsigned BasePtr = (TFI->hasFP(MF) ? MSP430::R4 : MSP430::SP);
1160b57cec5SDimitry Andric   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   // Skip the saved PC
1190b57cec5SDimitry Andric   Offset += 2;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   if (!TFI->hasFP(MF))
1220b57cec5SDimitry Andric     Offset += MF.getFrameInfo().getStackSize();
1230b57cec5SDimitry Andric   else
1240b57cec5SDimitry Andric     Offset += 2; // Skip the saved FP
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   // Fold imm into offset
1270b57cec5SDimitry Andric   Offset += MI.getOperand(FIOperandNum + 1).getImm();
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   if (MI.getOpcode() == MSP430::ADDframe) {
1300b57cec5SDimitry Andric     // This is actually "load effective address" of the stack slot
1310b57cec5SDimitry Andric     // instruction. We have only two-address instructions, thus we need to
1320b57cec5SDimitry Andric     // expand it into mov + add
1330b57cec5SDimitry Andric     const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     MI.setDesc(TII.get(MSP430::MOV16rr));
1360b57cec5SDimitry Andric     MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
1370b57cec5SDimitry Andric 
138*5f757f3fSDimitry Andric     // Remove the now unused Offset operand.
139*5f757f3fSDimitry Andric     MI.removeOperand(FIOperandNum + 1);
140*5f757f3fSDimitry Andric 
1410b57cec5SDimitry Andric     if (Offset == 0)
142bdd1243dSDimitry Andric       return false;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric     // We need to materialize the offset via add instruction.
1458bcb0991SDimitry Andric     Register DstReg = MI.getOperand(0).getReg();
1460b57cec5SDimitry Andric     if (Offset < 0)
1470b57cec5SDimitry Andric       BuildMI(MBB, std::next(II), dl, TII.get(MSP430::SUB16ri), DstReg)
1480b57cec5SDimitry Andric         .addReg(DstReg).addImm(-Offset);
1490b57cec5SDimitry Andric     else
1500b57cec5SDimitry Andric       BuildMI(MBB, std::next(II), dl, TII.get(MSP430::ADD16ri), DstReg)
1510b57cec5SDimitry Andric         .addReg(DstReg).addImm(Offset);
1520b57cec5SDimitry Andric 
153bdd1243dSDimitry Andric     return false;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
1570b57cec5SDimitry Andric   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
158bdd1243dSDimitry Andric   return false;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const1610b57cec5SDimitry Andric Register MSP430RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
1620b57cec5SDimitry Andric   const MSP430FrameLowering *TFI = getFrameLowering(MF);
1635ffd83dbSDimitry Andric   return TFI->hasFP(MF) ? MSP430::R4 : MSP430::SP;
1640b57cec5SDimitry Andric }
165