1//===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "MipsABIInfo.h"
10#include "Mips.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/MC/MCTargetOptions.h"
13
14using namespace llvm;
15
16namespace {
17static constexpr MCPhysReg O32IntRegs[] = {Mips::R4, Mips::R5, Mips::R6,
18 Mips::R7};
19static constexpr MCPhysReg NABIIntRegs[] = {Mips::R4, Mips::R5, Mips::R6,
20 Mips::R7, Mips::R8, Mips::R9,
21 Mips::R10, Mips::R11};
22static constexpr MCPhysReg Mips64IntRegs[] = {
23 Mips::R4_64, Mips::R5_64, Mips::R6_64, Mips::R7_64,
24 Mips::R8_64, Mips::R9_64, Mips::R10_64, Mips::R11_64};
25
26struct GPR {
27 MCPhysReg Reg32;
28 MCPhysReg Reg64;
29};
30
31static constexpr GPR OABITempRegs[] = {
32 {.Reg32: Mips::R8, .Reg64: Mips::R8_64}, {.Reg32: Mips::R9, .Reg64: Mips::R9_64},
33 {.Reg32: Mips::R10, .Reg64: Mips::R10_64}, {.Reg32: Mips::R11, .Reg64: Mips::R11_64},
34 {.Reg32: Mips::R12, .Reg64: Mips::R12_64}, {.Reg32: Mips::R13, .Reg64: Mips::R13_64},
35 {.Reg32: Mips::R14, .Reg64: Mips::R14_64}, {.Reg32: Mips::R15, .Reg64: Mips::R15_64},
36 {.Reg32: Mips::R24, .Reg64: Mips::R24_64}, {.Reg32: Mips::R25, .Reg64: Mips::R25_64},
37};
38
39static constexpr GPR NABITempRegs[] = {
40 {.Reg32: Mips::R12, .Reg64: Mips::R12_64},
41 {.Reg32: Mips::R13, .Reg64: Mips::R13_64},
42 {.Reg32: Mips::R14, .Reg64: Mips::R14_64},
43 {.Reg32: Mips::R15, .Reg64: Mips::R15_64},
44 {.Reg32: Mips::NoRegister, .Reg64: Mips::NoRegister},
45 {.Reg32: Mips::NoRegister, .Reg64: Mips::NoRegister},
46 {.Reg32: Mips::NoRegister, .Reg64: Mips::NoRegister},
47 {.Reg32: Mips::NoRegister, .Reg64: Mips::NoRegister},
48 {.Reg32: Mips::R24, .Reg64: Mips::R24_64},
49 {.Reg32: Mips::R25, .Reg64: Mips::R25_64},
50};
51
52static constexpr GPR PABITempRegs[] = {
53 {.Reg32: Mips::R12, .Reg64: Mips::R12_64},
54 {.Reg32: Mips::R13, .Reg64: Mips::R13_64},
55 {.Reg32: Mips::R14, .Reg64: Mips::R14_64},
56 {.Reg32: Mips::R15, .Reg64: Mips::R15_64},
57 {.Reg32: Mips::R2, .Reg64: Mips::R2_64},
58 {.Reg32: Mips::R3, .Reg64: Mips::R3_64},
59 {.Reg32: Mips::NoRegister, .Reg64: Mips::NoRegister},
60 {.Reg32: Mips::NoRegister, .Reg64: Mips::NoRegister},
61 {.Reg32: Mips::R24, .Reg64: Mips::R24_64},
62 {.Reg32: Mips::R25, .Reg64: Mips::R25_64},
63};
64
65static constexpr GPR SavedRegs[] = {
66 {.Reg32: Mips::R16, .Reg64: Mips::R16_64}, {.Reg32: Mips::R17, .Reg64: Mips::R17_64},
67 {.Reg32: Mips::R18, .Reg64: Mips::R18_64}, {.Reg32: Mips::R19, .Reg64: Mips::R19_64},
68 {.Reg32: Mips::R20, .Reg64: Mips::R20_64}, {.Reg32: Mips::R21, .Reg64: Mips::R21_64},
69 {.Reg32: Mips::R22, .Reg64: Mips::R22_64}, {.Reg32: Mips::R23, .Reg64: Mips::R23_64},
70};
71
72static constexpr GPR ReturnRegs[] = {
73 {.Reg32: Mips::R2, .Reg64: Mips::R2_64},
74 {.Reg32: Mips::R3, .Reg64: Mips::R3_64},
75};
76
77MCRegister getReg(ArrayRef<GPR> Regs, unsigned I, bool Is64Bit) {
78 assert(I < Regs.size() && "Invalid ABI register index");
79 MCRegister Reg = Is64Bit ? Regs[I].Reg64 : Regs[I].Reg32;
80 assert(Reg && "Register name is not defined by this ABI");
81 return Reg;
82}
83} // namespace
84
85ArrayRef<MCPhysReg> MipsABIInfo::getArgRegs(bool Is64Bit) const {
86 assert(IsKnown() && "Unknown ABI");
87 if (Is64Bit)
88 return ArrayRef(Mips64IntRegs).take_front(N: IsO32() ? 4 : 8);
89 return IsO32() ? ArrayRef(O32IntRegs) : ArrayRef(NABIIntRegs);
90}
91
92ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const {
93 return getArgRegs(Is64Bit: AreGprs64bit());
94}
95
96unsigned MipsABIInfo::getRegAltNameIndex() const {
97 switch (ThisABI) {
98 case ABI::O32:
99 return Mips::OABIRegAltName;
100 case ABI::N32:
101 case ABI::N64:
102 return Mips::NABIRegAltName;
103 case ABI::Unknown:
104 llvm_unreachable("Unknown ABI");
105 }
106 llvm_unreachable("Unhandled ABI");
107}
108
109MCRegister MipsABIInfo::getArgReg(unsigned I, bool Is64Bit) const {
110 ArrayRef<MCPhysReg> Regs = getArgRegs(Is64Bit);
111 assert(I < Regs.size() && "Invalid argument register");
112 return Regs[I];
113}
114
115MCRegister MipsABIInfo::getTempReg(unsigned I, bool Is64Bit) const {
116 switch (getRegAltNameIndex()) {
117 case Mips::OABIRegAltName:
118 return getReg(Regs: OABITempRegs, I, Is64Bit);
119 case Mips::NABIRegAltName:
120 return getReg(Regs: NABITempRegs, I, Is64Bit);
121 case Mips::PABIRegAltName:
122 return getReg(Regs: PABITempRegs, I, Is64Bit);
123 default:
124 llvm_unreachable("Unknown register naming convention");
125 }
126}
127
128MCRegister MipsABIInfo::getSavedReg(unsigned I, bool Is64Bit) const {
129 assert(IsKnown() && "Unknown ABI");
130 return getReg(Regs: SavedRegs, I, Is64Bit);
131}
132
133MCRegister MipsABIInfo::getReturnReg(unsigned I, bool Is64Bit) const {
134 switch (ThisABI) {
135 case ABI::O32:
136 case ABI::N32:
137 case ABI::N64:
138 return getReg(Regs: ReturnRegs, I, Is64Bit);
139 case ABI::Unknown:
140 llvm_unreachable("Unknown ABI");
141 }
142 llvm_unreachable("Unhandled ABI");
143}
144
145ArrayRef<MCPhysReg> MipsABIInfo::getVarArgRegs(bool isGP64bit) const {
146 if (IsO32()) {
147 if (isGP64bit)
148 return ArrayRef(Mips64IntRegs);
149 else
150 return ArrayRef(O32IntRegs);
151 }
152 if (IsN32() || IsN64())
153 return ArrayRef(Mips64IntRegs);
154 llvm_unreachable("Unhandled ABI");
155}
156
157unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const {
158 if (IsO32())
159 return CC != CallingConv::Fast ? 16 : 0;
160 if (IsN32() || IsN64())
161 return 0;
162 llvm_unreachable("Unhandled ABI");
163}
164
165MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef ABIName) {
166 if (ABIName.starts_with(Prefix: "o32"))
167 return MipsABIInfo::O32();
168 if (ABIName.starts_with(Prefix: "n32"))
169 return MipsABIInfo::N32();
170 if (ABIName.starts_with(Prefix: "n64"))
171 return MipsABIInfo::N64();
172 if (TT.isABIN32())
173 return MipsABIInfo::N32();
174 assert(ABIName.empty() && "Unknown ABI option for MIPS");
175
176 if (TT.isMIPS64())
177 return MipsABIInfo::N64();
178 return MipsABIInfo::O32();
179}
180
181unsigned MipsABIInfo::GetStackPtr() const {
182 return ArePtrs64bit() ? Mips::SP_64 : Mips::SP;
183}
184
185unsigned MipsABIInfo::GetFramePtr() const {
186 return ArePtrs64bit() ? Mips::FP_64 : Mips::FP;
187}
188
189unsigned MipsABIInfo::GetBasePtr() const { return getSavedRegPtr(I: 7); }
190
191unsigned MipsABIInfo::GetGlobalPtr() const {
192 return ArePtrs64bit() ? Mips::GP_64 : Mips::GP;
193}
194
195unsigned MipsABIInfo::GetNullPtr() const {
196 return ArePtrs64bit() ? Mips::R0_64 : Mips::R0;
197}
198
199unsigned MipsABIInfo::GetZeroReg() const {
200 return AreGprs64bit() ? Mips::R0_64 : Mips::R0;
201}
202
203unsigned MipsABIInfo::GetPtrAdduOp() const {
204 return ArePtrs64bit() ? Mips::DADDu : Mips::ADDu;
205}
206
207unsigned MipsABIInfo::GetPtrAddiuOp() const {
208 return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu;
209}
210
211unsigned MipsABIInfo::GetPtrSubuOp() const {
212 return ArePtrs64bit() ? Mips::DSUBu : Mips::SUBu;
213}
214
215unsigned MipsABIInfo::GetPtrAndOp() const {
216 return ArePtrs64bit() ? Mips::AND64 : Mips::AND;
217}
218
219unsigned MipsABIInfo::GetGPRMoveOp() const {
220 return ArePtrs64bit() ? Mips::OR64 : Mips::OR;
221}
222
223unsigned MipsABIInfo::GetEhDataReg(unsigned I) const {
224 assert(I < 4 && "Invalid EH data register");
225 return getArgRegPtr(I);
226}
227