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