XCoreRegisterInfo.cpp revision 210299
1//===- XCoreRegisterInfo.cpp - XCore Register Information -------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the XCore implementation of the MRegisterInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "XCoreRegisterInfo.h"
15#include "XCoreMachineFunctionInfo.h"
16#include "XCore.h"
17#include "llvm/CodeGen/MachineInstrBuilder.h"
18#include "llvm/CodeGen/MachineFunction.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineLocation.h"
21#include "llvm/CodeGen/MachineModuleInfo.h"
22#include "llvm/CodeGen/MachineRegisterInfo.h"
23#include "llvm/CodeGen/RegisterScavenging.h"
24#include "llvm/Target/TargetFrameInfo.h"
25#include "llvm/Target/TargetMachine.h"
26#include "llvm/Target/TargetOptions.h"
27#include "llvm/Target/TargetInstrInfo.h"
28#include "llvm/Type.h"
29#include "llvm/Function.h"
30#include "llvm/ADT/BitVector.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/raw_ostream.h"
35
36using namespace llvm;
37
38XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii)
39  : XCoreGenRegisterInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
40    TII(tii) {
41}
42
43// helper functions
44static inline bool isImmUs(unsigned val) {
45  return val <= 11;
46}
47
48static inline bool isImmU6(unsigned val) {
49  return val < (1 << 6);
50}
51
52static inline bool isImmU16(unsigned val) {
53  return val < (1 << 16);
54}
55
56static const unsigned XCore_ArgRegs[] = {
57  XCore::R0, XCore::R1, XCore::R2, XCore::R3
58};
59
60const unsigned * XCoreRegisterInfo::getArgRegs(const MachineFunction *MF)
61{
62  return XCore_ArgRegs;
63}
64
65unsigned XCoreRegisterInfo::getNumArgRegs(const MachineFunction *MF)
66{
67  return array_lengthof(XCore_ArgRegs);
68}
69
70bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
71  return MF.getMMI().hasDebugInfo() || !MF.getFunction()->doesNotThrow() ||
72          UnwindTablesMandatory;
73}
74
75const unsigned* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
76                                                                         const {
77  static const unsigned CalleeSavedRegs[] = {
78    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
79    XCore::R8, XCore::R9, XCore::R10, XCore::LR,
80    0
81  };
82  return CalleeSavedRegs;
83}
84
85BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
86  BitVector Reserved(getNumRegs());
87  Reserved.set(XCore::CP);
88  Reserved.set(XCore::DP);
89  Reserved.set(XCore::SP);
90  Reserved.set(XCore::LR);
91  if (hasFP(MF)) {
92    Reserved.set(XCore::R10);
93  }
94  return Reserved;
95}
96
97bool
98XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
99  // TODO can we estimate stack size?
100  return hasFP(MF);
101}
102
103bool XCoreRegisterInfo::hasFP(const MachineFunction &MF) const {
104  return DisableFramePointerElim(MF) || MF.getFrameInfo()->hasVarSizedObjects();
105}
106
107// This function eliminates ADJCALLSTACKDOWN,
108// ADJCALLSTACKUP pseudo instructions
109void XCoreRegisterInfo::
110eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
111                              MachineBasicBlock::iterator I) const {
112  if (!hasReservedCallFrame(MF)) {
113    // Turn the adjcallstackdown instruction into 'extsp <amt>' and the
114    // adjcallstackup instruction into 'ldaw sp, sp[<amt>]'
115    MachineInstr *Old = I;
116    uint64_t Amount = Old->getOperand(0).getImm();
117    if (Amount != 0) {
118      // We need to keep the stack aligned properly.  To do this, we round the
119      // amount of space needed for the outgoing arguments up to the next
120      // alignment boundary.
121      unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
122      Amount = (Amount+Align-1)/Align*Align;
123
124      assert(Amount%4 == 0);
125      Amount /= 4;
126
127      bool isU6 = isImmU6(Amount);
128
129      if (!isU6 && !isImmU16(Amount)) {
130        // FIX could emit multiple instructions in this case.
131#ifndef NDEBUG
132        errs() << "eliminateCallFramePseudoInstr size too big: "
133               << Amount << "\n";
134#endif
135        llvm_unreachable(0);
136      }
137
138      MachineInstr *New;
139      if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) {
140        int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
141        New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode))
142          .addImm(Amount);
143      } else {
144        assert(Old->getOpcode() == XCore::ADJCALLSTACKUP);
145        int Opcode = isU6 ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
146        New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP)
147          .addImm(Amount);
148      }
149
150      // Replace the pseudo instruction with a new instruction...
151      MBB.insert(I, New);
152    }
153  }
154
155  MBB.erase(I);
156}
157
158unsigned
159XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
160                                       int SPAdj, FrameIndexValue *Value,
161                                       RegScavenger *RS) const {
162  assert(SPAdj == 0 && "Unexpected");
163  MachineInstr &MI = *II;
164  DebugLoc dl = MI.getDebugLoc();
165  unsigned i = 0;
166
167  while (!MI.getOperand(i).isFI()) {
168    ++i;
169    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
170  }
171
172  MachineOperand &FrameOp = MI.getOperand(i);
173  int FrameIndex = FrameOp.getIndex();
174
175  MachineFunction &MF = *MI.getParent()->getParent();
176  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
177  int StackSize = MF.getFrameInfo()->getStackSize();
178
179  #ifndef NDEBUG
180  DEBUG(errs() << "\nFunction         : "
181        << MF.getFunction()->getName() << "\n");
182  DEBUG(errs() << "<--------->\n");
183  DEBUG(MI.print(errs()));
184  DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
185  DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
186  DEBUG(errs() << "StackSize          : " << StackSize << "\n");
187  #endif
188
189  Offset += StackSize;
190
191  // fold constant into offset.
192  Offset += MI.getOperand(i + 1).getImm();
193  MI.getOperand(i + 1).ChangeToImmediate(0);
194
195  assert(Offset%4 == 0 && "Misaligned stack offset");
196
197  DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
198
199  Offset/=4;
200
201  bool FP = hasFP(MF);
202
203  unsigned Reg = MI.getOperand(0).getReg();
204  bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill();
205
206  assert(XCore::GRRegsRegisterClass->contains(Reg) &&
207         "Unexpected register operand");
208
209  MachineBasicBlock &MBB = *MI.getParent();
210
211  if (FP) {
212    bool isUs = isImmUs(Offset);
213    unsigned FramePtr = XCore::R10;
214
215    if (!isUs) {
216      if (!RS)
217        report_fatal_error("eliminateFrameIndex Frame size too big: " +
218                           Twine(Offset));
219      unsigned ScratchReg = RS->scavengeRegister(XCore::GRRegsRegisterClass, II,
220                                                 SPAdj);
221      loadConstant(MBB, II, ScratchReg, Offset, dl);
222      switch (MI.getOpcode()) {
223      case XCore::LDWFI:
224        BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
225              .addReg(FramePtr)
226              .addReg(ScratchReg, RegState::Kill);
227        break;
228      case XCore::STWFI:
229        BuildMI(MBB, II, dl, TII.get(XCore::STW_3r))
230              .addReg(Reg, getKillRegState(isKill))
231              .addReg(FramePtr)
232              .addReg(ScratchReg, RegState::Kill);
233        break;
234      case XCore::LDAWFI:
235        BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
236              .addReg(FramePtr)
237              .addReg(ScratchReg, RegState::Kill);
238        break;
239      default:
240        llvm_unreachable("Unexpected Opcode");
241      }
242    } else {
243      switch (MI.getOpcode()) {
244      case XCore::LDWFI:
245        BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
246              .addReg(FramePtr)
247              .addImm(Offset);
248        break;
249      case XCore::STWFI:
250        BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
251              .addReg(Reg, getKillRegState(isKill))
252              .addReg(FramePtr)
253              .addImm(Offset);
254        break;
255      case XCore::LDAWFI:
256        BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
257              .addReg(FramePtr)
258              .addImm(Offset);
259        break;
260      default:
261        llvm_unreachable("Unexpected Opcode");
262      }
263    }
264  } else {
265    bool isU6 = isImmU6(Offset);
266    if (!isU6 && !isImmU16(Offset))
267      report_fatal_error("eliminateFrameIndex Frame size too big: " +
268                         Twine(Offset));
269
270    switch (MI.getOpcode()) {
271    int NewOpcode;
272    case XCore::LDWFI:
273      NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
274      BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
275            .addImm(Offset);
276      break;
277    case XCore::STWFI:
278      NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
279      BuildMI(MBB, II, dl, TII.get(NewOpcode))
280            .addReg(Reg, getKillRegState(isKill))
281            .addImm(Offset);
282      break;
283    case XCore::LDAWFI:
284      NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
285      BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
286            .addImm(Offset);
287      break;
288    default:
289      llvm_unreachable("Unexpected Opcode");
290    }
291  }
292  // Erase old instruction.
293  MBB.erase(II);
294  return 0;
295}
296
297void
298XCoreRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
299                                                      RegScavenger *RS) const {
300  MachineFrameInfo *MFI = MF.getFrameInfo();
301  bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
302  const TargetRegisterClass *RC = XCore::GRRegsRegisterClass;
303  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
304  if (LRUsed) {
305    MF.getRegInfo().setPhysRegUnused(XCore::LR);
306
307    bool isVarArg = MF.getFunction()->isVarArg();
308    int FrameIdx;
309    if (! isVarArg) {
310      // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
311      FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
312    } else {
313      FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
314                                        false);
315    }
316    XFI->setUsesLR(FrameIdx);
317    XFI->setLRSpillSlot(FrameIdx);
318  }
319  if (requiresRegisterScavenging(MF)) {
320    // Reserve a slot close to SP or frame pointer.
321    RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
322                                                       RC->getAlignment(),
323                                                       false));
324  }
325  if (hasFP(MF)) {
326    // A callee save register is used to hold the FP.
327    // This needs saving / restoring in the epilogue / prologue.
328    XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
329                                               RC->getAlignment(),
330                                               false));
331  }
332}
333
334void XCoreRegisterInfo::
335processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
336
337}
338
339void XCoreRegisterInfo::
340loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
341            unsigned DstReg, int64_t Value, DebugLoc dl) const {
342  // TODO use mkmsk if possible.
343  if (!isImmU16(Value)) {
344    // TODO use constant pool.
345    report_fatal_error("loadConstant value too big " + Twine(Value));
346  }
347  int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
348  BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
349}
350
351void XCoreRegisterInfo::
352storeToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
353                  unsigned SrcReg, int Offset, DebugLoc dl) const {
354  assert(Offset%4 == 0 && "Misaligned stack offset");
355  Offset/=4;
356  bool isU6 = isImmU6(Offset);
357  if (!isU6 && !isImmU16(Offset))
358    report_fatal_error("storeToStack offset too big " + Twine(Offset));
359  int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
360  BuildMI(MBB, I, dl, TII.get(Opcode))
361    .addReg(SrcReg)
362    .addImm(Offset);
363}
364
365void XCoreRegisterInfo::
366loadFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
367                  unsigned DstReg, int Offset, DebugLoc dl) const {
368  assert(Offset%4 == 0 && "Misaligned stack offset");
369  Offset/=4;
370  bool isU6 = isImmU6(Offset);
371  if (!isU6 && !isImmU16(Offset))
372    report_fatal_error("loadFromStack offset too big " + Twine(Offset));
373  int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
374  BuildMI(MBB, I, dl, TII.get(Opcode), DstReg)
375    .addImm(Offset);
376}
377
378void XCoreRegisterInfo::emitPrologue(MachineFunction &MF) const {
379  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
380  MachineBasicBlock::iterator MBBI = MBB.begin();
381  MachineFrameInfo *MFI = MF.getFrameInfo();
382  MachineModuleInfo *MMI = &MF.getMMI();
383  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
384  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
385
386  bool FP = hasFP(MF);
387
388  // Work out frame sizes.
389  int FrameSize = MFI->getStackSize();
390
391  assert(FrameSize%4 == 0 && "Misaligned frame size");
392
393  FrameSize/=4;
394
395  bool isU6 = isImmU6(FrameSize);
396
397  if (!isU6 && !isImmU16(FrameSize)) {
398    // FIXME could emit multiple instructions.
399    report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
400  }
401  bool emitFrameMoves = needsFrameMoves(MF);
402
403  // Do we need to allocate space on the stack?
404  if (FrameSize) {
405    bool saveLR = XFI->getUsesLR();
406    bool LRSavedOnEntry = false;
407    int Opcode;
408    if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
409      Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
410      MBB.addLiveIn(XCore::LR);
411      saveLR = false;
412      LRSavedOnEntry = true;
413    } else {
414      Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
415    }
416    BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
417
418    if (emitFrameMoves) {
419      std::vector<MachineMove> &Moves = MMI->getFrameMoves();
420
421      // Show update of SP.
422      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
423      BuildMI(MBB, MBBI, dl, TII.get(XCore::DBG_LABEL)).addSym(FrameLabel);
424
425      MachineLocation SPDst(MachineLocation::VirtualFP);
426      MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4);
427      Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
428
429      if (LRSavedOnEntry) {
430        MachineLocation CSDst(MachineLocation::VirtualFP, 0);
431        MachineLocation CSSrc(XCore::LR);
432        Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
433      }
434    }
435    if (saveLR) {
436      int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
437      storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl);
438      MBB.addLiveIn(XCore::LR);
439
440      if (emitFrameMoves) {
441        MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
442        BuildMI(MBB, MBBI, dl, TII.get(XCore::DBG_LABEL)).addSym(SaveLRLabel);
443        MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset);
444        MachineLocation CSSrc(XCore::LR);
445        MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc));
446      }
447    }
448  }
449
450  if (FP) {
451    // Save R10 to the stack.
452    int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
453    storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl);
454    // R10 is live-in. It is killed at the spill.
455    MBB.addLiveIn(XCore::R10);
456    if (emitFrameMoves) {
457      MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
458      BuildMI(MBB, MBBI, dl, TII.get(XCore::DBG_LABEL)).addSym(SaveR10Label);
459      MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset);
460      MachineLocation CSSrc(XCore::R10);
461      MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc));
462    }
463    // Set the FP from the SP.
464    unsigned FramePtr = XCore::R10;
465    BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr)
466      .addImm(0);
467    if (emitFrameMoves) {
468      // Show FP is now valid.
469      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
470      BuildMI(MBB, MBBI, dl, TII.get(XCore::DBG_LABEL)).addSym(FrameLabel);
471      MachineLocation SPDst(FramePtr);
472      MachineLocation SPSrc(MachineLocation::VirtualFP);
473      MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc));
474    }
475  }
476
477  if (emitFrameMoves) {
478    // Frame moves for callee saved.
479    std::vector<MachineMove> &Moves = MMI->getFrameMoves();
480    std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels =
481        XFI->getSpillLabels();
482    for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) {
483      MCSymbol *SpillLabel = SpillLabels[I].first;
484      CalleeSavedInfo &CSI = SpillLabels[I].second;
485      int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
486      unsigned Reg = CSI.getReg();
487      MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
488      MachineLocation CSSrc(Reg);
489      Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc));
490    }
491  }
492}
493
494void XCoreRegisterInfo::emitEpilogue(MachineFunction &MF,
495                                     MachineBasicBlock &MBB) const {
496  MachineFrameInfo *MFI            = MF.getFrameInfo();
497  MachineBasicBlock::iterator MBBI = prior(MBB.end());
498  DebugLoc dl = MBBI->getDebugLoc();
499
500  bool FP = hasFP(MF);
501
502  if (FP) {
503    // Restore the stack pointer.
504    unsigned FramePtr = XCore::R10;
505    BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
506      .addReg(FramePtr);
507  }
508
509  // Work out frame sizes.
510  int FrameSize = MFI->getStackSize();
511
512  assert(FrameSize%4 == 0 && "Misaligned frame size");
513
514  FrameSize/=4;
515
516  bool isU6 = isImmU6(FrameSize);
517
518  if (!isU6 && !isImmU16(FrameSize)) {
519    // FIXME could emit multiple instructions.
520    report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
521  }
522
523  if (FrameSize) {
524    XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
525
526    if (FP) {
527      // Restore R10
528      int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
529      FPSpillOffset += FrameSize*4;
530      loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl);
531    }
532    bool restoreLR = XFI->getUsesLR();
533    if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) {
534      int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
535      LRSpillOffset += FrameSize*4;
536      loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl);
537      restoreLR = false;
538    }
539    if (restoreLR) {
540      // Fold prologue into return instruction
541      assert(MBBI->getOpcode() == XCore::RETSP_u6
542        || MBBI->getOpcode() == XCore::RETSP_lu6);
543      int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
544      BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
545      MBB.erase(MBBI);
546    } else {
547      int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
548      BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
549    }
550  }
551}
552
553int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
554  return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
555}
556
557unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
558  bool FP = hasFP(MF);
559
560  return FP ? XCore::R10 : XCore::SP;
561}
562
563unsigned XCoreRegisterInfo::getRARegister() const {
564  return XCore::LR;
565}
566
567void XCoreRegisterInfo::getInitialFrameState(std::vector<MachineMove> &Moves)
568                                                                         const {
569  // Initial state of the frame pointer is SP.
570  MachineLocation Dst(MachineLocation::VirtualFP);
571  MachineLocation Src(XCore::SP, 0);
572  Moves.push_back(MachineMove(0, Dst, Src));
573}
574
575#include "XCoreGenRegisterInfo.inc"
576
577