131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//=== ARMCallingConv.h - ARM Custom Calling Convention Routines -*- C++ -*-===//
26f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//
36f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//                     The LLVM Compiler Infrastructure
46f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//
56f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher// This file is distributed under the University of Illinois Open Source
66f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher// License. See LICENSE.TXT for details.
76f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//
86f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//===----------------------------------------------------------------------===//
96f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//
106f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher// This file contains the custom routines for the ARM Calling Convention that
116f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher// aren't done by tablegen.
126f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//
136f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher//===----------------------------------------------------------------------===//
146f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
156f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher#ifndef ARMCALLINGCONV_H
166f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher#define ARMCALLINGCONV_H
176f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
18c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "ARM.h"
196f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher#include "ARMBaseInstrInfo.h"
206f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher#include "ARMSubtarget.h"
21c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "llvm/CallingConv.h"
22c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "llvm/CodeGen/CallingConvLower.h"
23c1f6f42049696e7357fb4837e1b25dabbaed3fe6Craig Topper#include "llvm/Target/TargetInstrInfo.h"
246f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
256f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christophernamespace llvm {
266f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
276f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher// APCS f64 is in register pairs, possibly split to stack
281e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
296f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                          CCValAssign::LocInfo &LocInfo,
306f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                          CCState &State, bool CanFail) {
31c5eaae4e9bc75b203b3a9922b480729bc4f340e2Craig Topper  static const uint16_t RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
326f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
336f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  // Try to get the first register.
346f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (unsigned Reg = State.AllocateReg(RegList, 4))
356f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
366f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  else {
376f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    // For the 2nd half of a v2f64, do not fail.
386f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    if (CanFail)
396f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher      return false;
406f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
416f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    // Put the whole thing on the stack.
426f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
436f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                           State.AllocateStack(8, 4),
446f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                           LocVT, LocInfo));
456f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return true;
466f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  }
476f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
486f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  // Try to get the second register.
496f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (unsigned Reg = State.AllocateReg(RegList, 4))
506f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
516f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  else
526f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
536f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                           State.AllocateStack(4, 4),
546f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                           LocVT, LocInfo));
556f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return true;
566f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
576f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
581e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
596f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                   CCValAssign::LocInfo &LocInfo,
606f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                   ISD::ArgFlagsTy &ArgFlags,
616f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                   CCState &State) {
626f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
636f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false;
646f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (LocVT == MVT::v2f64 &&
656f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher      !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
666f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false;
676f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return true;  // we handled it
686f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
696f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
706f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher// AAPCS f64 is in aligned register pairs
711e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
726f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                           CCValAssign::LocInfo &LocInfo,
736f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                           CCState &State, bool CanFail) {
74c5eaae4e9bc75b203b3a9922b480729bc4f340e2Craig Topper  static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 };
75c5eaae4e9bc75b203b3a9922b480729bc4f340e2Craig Topper  static const uint16_t LoRegList[] = { ARM::R1, ARM::R3 };
76c5eaae4e9bc75b203b3a9922b480729bc4f340e2Craig Topper  static const uint16_t ShadowRegList[] = { ARM::R0, ARM::R1 };
776f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
786f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2);
796f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (Reg == 0) {
806f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    // For the 2nd half of a v2f64, do not just fail.
816f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    if (CanFail)
826f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher      return false;
836f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
846f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    // Put the whole thing on the stack.
856f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
866f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                           State.AllocateStack(8, 8),
876f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                           LocVT, LocInfo));
886f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return true;
896f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  }
906f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
916f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  unsigned i;
926f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  for (i = 0; i < 2; ++i)
936f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    if (HiRegList[i] == Reg)
946f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher      break;
956f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
966f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  unsigned T = State.AllocateReg(LoRegList[i]);
976f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  (void)T;
986f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  assert(T == LoRegList[i] && "Could not allocate register");
996f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1006f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1016f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
1026f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                         LocVT, LocInfo));
1036f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return true;
1046f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
1056f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1061e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
1076f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                    CCValAssign::LocInfo &LocInfo,
1086f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                    ISD::ArgFlagsTy &ArgFlags,
1096f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                    CCState &State) {
1106f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
1116f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false;
1126f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (LocVT == MVT::v2f64 &&
1136f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher      !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
1146f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false;
1156f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return true;  // we handled it
1166f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
1176f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1181e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
1196f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                         CCValAssign::LocInfo &LocInfo, CCState &State) {
120c5eaae4e9bc75b203b3a9922b480729bc4f340e2Craig Topper  static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 };
121c5eaae4e9bc75b203b3a9922b480729bc4f340e2Craig Topper  static const uint16_t LoRegList[] = { ARM::R1, ARM::R3 };
1226f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1236f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2);
1246f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (Reg == 0)
1256f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false; // we didn't handle it
1266f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1276f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  unsigned i;
1286f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  for (i = 0; i < 2; ++i)
1296f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    if (HiRegList[i] == Reg)
1306f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher      break;
1316f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1326f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1336f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
1346f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                         LocVT, LocInfo));
1356f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return true;
1366f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
1376f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1381e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
1396f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                      CCValAssign::LocInfo &LocInfo,
1406f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                      ISD::ArgFlagsTy &ArgFlags,
1416f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                      CCState &State) {
1426f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
1436f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false;
1446f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
1456f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher    return false;
1466f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return true;  // we handled it
1476f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
1486f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1491e96bab329eb23e4ce8a0dc3cc6b33a3f03d15bfDuncan Sandsstatic bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
1506f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                       CCValAssign::LocInfo &LocInfo,
1516f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                       ISD::ArgFlagsTy &ArgFlags,
1526f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                       CCState &State) {
1536f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher  return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
1546f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher                                   State);
1556f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher}
1566f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
1576f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher} // End llvm namespace
1586f2ccefdc069b6bd2e8f8b110fc3205b821a17a7Eric Christopher
15909b2171d7e78de240c4b510dd9808010a5e2efddEric Christopher#endif
160