185e72c3dSReid Kleckner //===-- PPCCallingConv.h - --------------------------------------*- C++ -*-===//
285e72c3dSReid Kleckner //
385e72c3dSReid Kleckner // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
485e72c3dSReid Kleckner // See https://llvm.org/LICENSE.txt for license information.
585e72c3dSReid Kleckner // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
685e72c3dSReid Kleckner //
785e72c3dSReid Kleckner //===----------------------------------------------------------------------===//
885e72c3dSReid Kleckner
985e72c3dSReid Kleckner #include "PPCRegisterInfo.h"
1085e72c3dSReid Kleckner #include "PPCCallingConv.h"
1185e72c3dSReid Kleckner #include "PPCSubtarget.h"
1285e72c3dSReid Kleckner #include "PPCCCState.h"
1385e72c3dSReid Kleckner using namespace llvm;
1485e72c3dSReid Kleckner
CC_PPC_AnyReg_Error(unsigned &,MVT &,MVT &,CCValAssign::LocInfo &,ISD::ArgFlagsTy &,CCState &)1585e72c3dSReid Kleckner inline bool CC_PPC_AnyReg_Error(unsigned &, MVT &, MVT &,
1685e72c3dSReid Kleckner CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
1785e72c3dSReid Kleckner CCState &) {
1885e72c3dSReid Kleckner llvm_unreachable("The AnyReg calling convention is only supported by the " \
1985e72c3dSReid Kleckner "stackmap and patchpoint intrinsics.");
2085e72c3dSReid Kleckner // gracefully fallback to PPC C calling convention on Release builds.
2185e72c3dSReid Kleckner return false;
2285e72c3dSReid Kleckner }
2385e72c3dSReid Kleckner
CC_PPC32_SVR4_Custom_Dummy(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)2485e72c3dSReid Kleckner static bool CC_PPC32_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
2585e72c3dSReid Kleckner CCValAssign::LocInfo &LocInfo,
2685e72c3dSReid Kleckner ISD::ArgFlagsTy &ArgFlags,
2785e72c3dSReid Kleckner CCState &State) {
2885e72c3dSReid Kleckner return true;
2985e72c3dSReid Kleckner }
3085e72c3dSReid Kleckner
CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)3185e72c3dSReid Kleckner static bool CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT,
3285e72c3dSReid Kleckner MVT &LocVT,
3385e72c3dSReid Kleckner CCValAssign::LocInfo &LocInfo,
3485e72c3dSReid Kleckner ISD::ArgFlagsTy &ArgFlags,
3585e72c3dSReid Kleckner CCState &State) {
3685e72c3dSReid Kleckner static const MCPhysReg ArgRegs[] = {
3785e72c3dSReid Kleckner PPC::R3, PPC::R4, PPC::R5, PPC::R6,
3885e72c3dSReid Kleckner PPC::R7, PPC::R8, PPC::R9, PPC::R10,
3985e72c3dSReid Kleckner };
40*f15014ffSBenjamin Kramer const unsigned NumArgRegs = array_lengthof(ArgRegs);
4185e72c3dSReid Kleckner
4285e72c3dSReid Kleckner unsigned RegNum = State.getFirstUnallocated(ArgRegs);
4385e72c3dSReid Kleckner
4485e72c3dSReid Kleckner // Skip one register if the first unallocated register has an even register
4585e72c3dSReid Kleckner // number and there are still argument registers available which have not been
4685e72c3dSReid Kleckner // allocated yet. RegNum is actually an index into ArgRegs, which means we
4785e72c3dSReid Kleckner // need to skip a register if RegNum is odd.
4885e72c3dSReid Kleckner if (RegNum != NumArgRegs && RegNum % 2 == 1) {
4985e72c3dSReid Kleckner State.AllocateReg(ArgRegs[RegNum]);
5085e72c3dSReid Kleckner }
5185e72c3dSReid Kleckner
5285e72c3dSReid Kleckner // Always return false here, as this function only makes sure that the first
5385e72c3dSReid Kleckner // unallocated register has an odd register number and does not actually
5485e72c3dSReid Kleckner // allocate a register for the current argument.
5585e72c3dSReid Kleckner return false;
5685e72c3dSReid Kleckner }
5785e72c3dSReid Kleckner
CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)5885e72c3dSReid Kleckner static bool CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(
5985e72c3dSReid Kleckner unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo,
6085e72c3dSReid Kleckner ISD::ArgFlagsTy &ArgFlags, CCState &State) {
6185e72c3dSReid Kleckner static const MCPhysReg ArgRegs[] = {
6285e72c3dSReid Kleckner PPC::R3, PPC::R4, PPC::R5, PPC::R6,
6385e72c3dSReid Kleckner PPC::R7, PPC::R8, PPC::R9, PPC::R10,
6485e72c3dSReid Kleckner };
65*f15014ffSBenjamin Kramer const unsigned NumArgRegs = array_lengthof(ArgRegs);
6685e72c3dSReid Kleckner
6785e72c3dSReid Kleckner unsigned RegNum = State.getFirstUnallocated(ArgRegs);
6885e72c3dSReid Kleckner int RegsLeft = NumArgRegs - RegNum;
6985e72c3dSReid Kleckner
7085e72c3dSReid Kleckner // Skip if there is not enough registers left for long double type (4 gpr regs
7185e72c3dSReid Kleckner // in soft float mode) and put long double argument on the stack.
7285e72c3dSReid Kleckner if (RegNum != NumArgRegs && RegsLeft < 4) {
7385e72c3dSReid Kleckner for (int i = 0; i < RegsLeft; i++) {
7485e72c3dSReid Kleckner State.AllocateReg(ArgRegs[RegNum + i]);
7585e72c3dSReid Kleckner }
7685e72c3dSReid Kleckner }
7785e72c3dSReid Kleckner
7885e72c3dSReid Kleckner return false;
7985e72c3dSReid Kleckner }
8085e72c3dSReid Kleckner
CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)8185e72c3dSReid Kleckner static bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT,
8285e72c3dSReid Kleckner MVT &LocVT,
8385e72c3dSReid Kleckner CCValAssign::LocInfo &LocInfo,
8485e72c3dSReid Kleckner ISD::ArgFlagsTy &ArgFlags,
8585e72c3dSReid Kleckner CCState &State) {
8685e72c3dSReid Kleckner static const MCPhysReg ArgRegs[] = {
8785e72c3dSReid Kleckner PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
8885e72c3dSReid Kleckner PPC::F8
8985e72c3dSReid Kleckner };
9085e72c3dSReid Kleckner
91*f15014ffSBenjamin Kramer const unsigned NumArgRegs = array_lengthof(ArgRegs);
9285e72c3dSReid Kleckner
9385e72c3dSReid Kleckner unsigned RegNum = State.getFirstUnallocated(ArgRegs);
9485e72c3dSReid Kleckner
9585e72c3dSReid Kleckner // If there is only one Floating-point register left we need to put both f64
9685e72c3dSReid Kleckner // values of a split ppc_fp128 value on the stack.
9785e72c3dSReid Kleckner if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) {
9885e72c3dSReid Kleckner State.AllocateReg(ArgRegs[RegNum]);
9985e72c3dSReid Kleckner }
10085e72c3dSReid Kleckner
10185e72c3dSReid Kleckner // Always return false here, as this function only makes sure that the two f64
10285e72c3dSReid Kleckner // values a ppc_fp128 value is split into are both passed in registers or both
10385e72c3dSReid Kleckner // passed on the stack and does not actually allocate a register for the
10485e72c3dSReid Kleckner // current argument.
10585e72c3dSReid Kleckner return false;
10685e72c3dSReid Kleckner }
10785e72c3dSReid Kleckner
1081d1cf30bSJustin Hibbits // Split F64 arguments into two 32-bit consecutive registers.
CC_PPC32_SPE_CustomSplitFP64(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)1091d1cf30bSJustin Hibbits static bool CC_PPC32_SPE_CustomSplitFP64(unsigned &ValNo, MVT &ValVT,
1101d1cf30bSJustin Hibbits MVT &LocVT,
1111d1cf30bSJustin Hibbits CCValAssign::LocInfo &LocInfo,
1121d1cf30bSJustin Hibbits ISD::ArgFlagsTy &ArgFlags,
1131d1cf30bSJustin Hibbits CCState &State) {
1141d1cf30bSJustin Hibbits static const MCPhysReg HiRegList[] = { PPC::R3, PPC::R5, PPC::R7, PPC::R9 };
1151d1cf30bSJustin Hibbits static const MCPhysReg LoRegList[] = { PPC::R4, PPC::R6, PPC::R8, PPC::R10 };
1161d1cf30bSJustin Hibbits
1171d1cf30bSJustin Hibbits // Try to get the first register.
1181d1cf30bSJustin Hibbits unsigned Reg = State.AllocateReg(HiRegList);
1191d1cf30bSJustin Hibbits if (!Reg)
1201d1cf30bSJustin Hibbits return false;
1211d1cf30bSJustin Hibbits
1221d1cf30bSJustin Hibbits unsigned i;
1231d1cf30bSJustin Hibbits for (i = 0; i < sizeof(HiRegList) / sizeof(HiRegList[0]); ++i)
1241d1cf30bSJustin Hibbits if (HiRegList[i] == Reg)
1251d1cf30bSJustin Hibbits break;
1261d1cf30bSJustin Hibbits
1271d1cf30bSJustin Hibbits unsigned T = State.AllocateReg(LoRegList[i]);
1281d1cf30bSJustin Hibbits (void)T;
1291d1cf30bSJustin Hibbits assert(T == LoRegList[i] && "Could not allocate register");
1301d1cf30bSJustin Hibbits
1311d1cf30bSJustin Hibbits State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1321d1cf30bSJustin Hibbits State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
1331d1cf30bSJustin Hibbits LocVT, LocInfo));
1341d1cf30bSJustin Hibbits return true;
1351d1cf30bSJustin Hibbits }
1361d1cf30bSJustin Hibbits
1371d1cf30bSJustin Hibbits // Same as above, but for return values, so only allocate for R3 and R4
CC_PPC32_SPE_RetF64(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)1381d1cf30bSJustin Hibbits static bool CC_PPC32_SPE_RetF64(unsigned &ValNo, MVT &ValVT,
1391d1cf30bSJustin Hibbits MVT &LocVT,
1401d1cf30bSJustin Hibbits CCValAssign::LocInfo &LocInfo,
1411d1cf30bSJustin Hibbits ISD::ArgFlagsTy &ArgFlags,
1421d1cf30bSJustin Hibbits CCState &State) {
1431d1cf30bSJustin Hibbits static const MCPhysReg HiRegList[] = { PPC::R3 };
1441d1cf30bSJustin Hibbits static const MCPhysReg LoRegList[] = { PPC::R4 };
1451d1cf30bSJustin Hibbits
1461d1cf30bSJustin Hibbits // Try to get the first register.
1471d1cf30bSJustin Hibbits unsigned Reg = State.AllocateReg(HiRegList, LoRegList);
1481d1cf30bSJustin Hibbits if (!Reg)
1491d1cf30bSJustin Hibbits return false;
1501d1cf30bSJustin Hibbits
1511d1cf30bSJustin Hibbits unsigned i;
1521d1cf30bSJustin Hibbits for (i = 0; i < sizeof(HiRegList) / sizeof(HiRegList[0]); ++i)
1531d1cf30bSJustin Hibbits if (HiRegList[i] == Reg)
1541d1cf30bSJustin Hibbits break;
1551d1cf30bSJustin Hibbits
1561d1cf30bSJustin Hibbits State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1571d1cf30bSJustin Hibbits State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
1581d1cf30bSJustin Hibbits LocVT, LocInfo));
1591d1cf30bSJustin Hibbits return true;
1601d1cf30bSJustin Hibbits }
1611d1cf30bSJustin Hibbits
16285e72c3dSReid Kleckner #include "PPCGenCallingConv.inc"
163