1 //==- SystemZRegisterInfo.td - SystemZ register definitions -*- tablegen -*-==//
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
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
13 class SystemZReg<string n> : Register<n> {
14 let Namespace = "SystemZ";
17 class SystemZRegWithSubregs<string n, list<Register> subregs>
18 : RegisterWithSubRegs<n, subregs> {
19 let Namespace = "SystemZ";
22 let Namespace = "SystemZ" in {
23 def subreg_l32 : SubRegIndex<32, 0>; // Also acts as subreg_hl32.
24 def subreg_h32 : SubRegIndex<32, 32>; // Also acts as subreg_hh32.
25 def subreg_l64 : SubRegIndex<64, 0>;
26 def subreg_h64 : SubRegIndex<64, 64>;
27 def subreg_lh32 : ComposedSubRegIndex<subreg_l64, subreg_h32>;
28 def subreg_ll32 : ComposedSubRegIndex<subreg_l64, subreg_l32>;
31 // Define a register class that contains values of types TYPES and an
32 // associated operand called NAME. SIZE is the size and alignment
33 // of the registers and REGLIST is the list of individual registers.
34 // If the user provides an alternate order list of regs, it will be used for
35 // XPLINK. Otherwise, by default, XPLINK will use the regList ordering as well
36 multiclass SystemZRegClass<string name, list<ValueType> types, int size,
37 dag regList, list<dag> altRegList = [regList], bit allocatable = 1> {
38 def AsmOperand : AsmOperandClass {
40 let ParserMethod = "parse"#name;
41 let RenderMethod = "addRegOperands";
43 let isAllocatable = allocatable in
44 def Bit : RegisterClass<"SystemZ", types, size, regList> {
46 let AltOrders = altRegList;
47 let AltOrderSelect = [{
48 const SystemZSubtarget &S = MF.getSubtarget<SystemZSubtarget>();
49 return S.isTargetXPLINK64();
52 def "" : RegisterOperand<!cast<RegisterClass>(name#"Bit")> {
53 let ParserMatchClass = !cast<AsmOperandClass>(name#"AsmOperand");
57 //===----------------------------------------------------------------------===//
58 // General-purpose registers
59 //===----------------------------------------------------------------------===//
61 // Lower 32 bits of one of the 16 64-bit general-purpose registers
62 class GPR32<bits<16> num, string n> : SystemZReg<n> {
66 // One of the 16 64-bit general-purpose registers.
67 class GPR64<bits<16> num, string n, GPR32 low, GPR32 high>
68 : SystemZRegWithSubregs<n, [low, high]> {
70 let SubRegIndices = [subreg_l32, subreg_h32];
71 let CoveredBySubRegs = 1;
74 // 8 even-odd pairs of GPR64s.
75 class GPR128<bits<16> num, string n, GPR64 low, GPR64 high>
76 : SystemZRegWithSubregs<n, [high, low]> {
78 let SubRegIndices = [subreg_h64, subreg_l64];
79 let CoveredBySubRegs = 1;
82 // General-purpose registers
84 def R#I#L : GPR32<I, "r"#I>;
85 def R#I#H : GPR32<I, "r"#I>;
86 def R#I#D : GPR64<I, "r"#I, !cast<GPR32>("R"#I#"L"), !cast<GPR32>("R"#I#"H")>,
90 foreach I = [0, 2, 4, 6, 8, 10, 12, 14] in {
91 def R#I#Q : GPR128<I, "r"#I, !cast<GPR64>("R"#!add(I, 1)#"D"),
92 !cast<GPR64>("R"#I#"D")>;
95 /// zLinux: Allocate the callee-saved R6-R13 backwards. That way they can be
96 /// saved together with R14 and R15 in one prolog instruction.
97 /// XPLINK64: Allocate all registers in natural order
98 defm GR32 : SystemZRegClass<"GR32", [i32], 32,
99 (add (sequence "R%uL", 0, 5),
100 (sequence "R%uL", 15, 6)),
101 [(add (sequence "R%uL", 0, 15))]>;
102 defm GRH32 : SystemZRegClass<"GRH32", [i32], 32,
103 (add (sequence "R%uH", 0, 5),
104 (sequence "R%uH", 15, 6)),
105 [(add (sequence "R%uH", 0, 15))]>;
106 defm GR64 : SystemZRegClass<"GR64", [i64], 64,
107 (add (sequence "R%uD", 0, 5),
108 (sequence "R%uD", 15, 6)),
109 [(add (sequence "R%uD", 0, 15))]>;
111 // Combine the low and high GR32s into a single class. This can only be
112 // used for virtual registers if the high-word facility is available.
113 /// XPLINK64: Allocate all registers in natural order
114 defm GRX32 : SystemZRegClass<"GRX32", [i32], 32,
115 (add (sequence "R%uL", 0, 5),
116 (sequence "R%uH", 0, 5),
117 R15L, R15H, R14L, R14H, R13L, R13H,
118 R12L, R12H, R11L, R11H, R10L, R10H,
119 R9L, R9H, R8L, R8H, R7L, R7H, R6L, R6H),
121 R0L, R1L, R2L, R3L, R0H, R1H, R2H, R3H,
122 R4L, R4H, R5L, R5H, R6L, R6H, R7L, R7H,
123 R8L, R8H, R9L, R9H, R10L,R10H,R11L,R11H,
124 R12L,R12H,R13L,R13H,R14L,R14H,R15L,R15H)
127 // On machines without SIMD support, i128 is not a legal type, so model the
128 // register pairs as untyped instead.
129 // XPLINK64: Allocate all registers in natural order
130 defm GR128 : SystemZRegClass<"GR128", [untyped], 128,
131 (add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q),
132 [(add R0Q, R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
134 // Base and index registers. Everything except R0, which in an address
135 // context evaluates as 0.
136 // XPLINK64: Allocate all registers in natural order
137 defm ADDR32 : SystemZRegClass<"ADDR32", [i32], 32, (sub GR32Bit, R0L),
138 [(add (sequence "R%uL", 1, 15))]>;
139 defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D),
140 [(add (sequence "R%uD", 1, 15))]>;
142 // Not used directly, but needs to exist for ADDR32 and ADDR64 subregs
144 // XPLINK64: Allocate all registers in natural order
145 defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q),
146 [(add R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
148 // Any type register. Used for .insn directives when we don't know what the
149 // register types could be.
150 defm AnyReg : SystemZRegClass<"AnyReg",
151 [i64, f64, v8i8, v4i16, v2i32, v2f32], 64,
152 (add (sequence "R%uD", 0, 15),
153 (sequence "F%uD", 0, 15),
154 (sequence "V%u", 0, 15)),
155 [], 0/*allocatable*/>;
157 //===----------------------------------------------------------------------===//
158 // Floating-point registers
159 //===----------------------------------------------------------------------===//
161 // Maps FPR register numbers to their DWARF encoding.
162 class DwarfMapping<int id> { int Id = id; }
164 def F0Dwarf : DwarfMapping<16>;
165 def F2Dwarf : DwarfMapping<17>;
166 def F4Dwarf : DwarfMapping<18>;
167 def F6Dwarf : DwarfMapping<19>;
169 def F1Dwarf : DwarfMapping<20>;
170 def F3Dwarf : DwarfMapping<21>;
171 def F5Dwarf : DwarfMapping<22>;
172 def F7Dwarf : DwarfMapping<23>;
174 def F8Dwarf : DwarfMapping<24>;
175 def F10Dwarf : DwarfMapping<25>;
176 def F12Dwarf : DwarfMapping<26>;
177 def F14Dwarf : DwarfMapping<27>;
179 def F9Dwarf : DwarfMapping<28>;
180 def F11Dwarf : DwarfMapping<29>;
181 def F13Dwarf : DwarfMapping<30>;
182 def F15Dwarf : DwarfMapping<31>;
184 def F16Dwarf : DwarfMapping<68>;
185 def F18Dwarf : DwarfMapping<69>;
186 def F20Dwarf : DwarfMapping<70>;
187 def F22Dwarf : DwarfMapping<71>;
189 def F17Dwarf : DwarfMapping<72>;
190 def F19Dwarf : DwarfMapping<73>;
191 def F21Dwarf : DwarfMapping<74>;
192 def F23Dwarf : DwarfMapping<75>;
194 def F24Dwarf : DwarfMapping<76>;
195 def F26Dwarf : DwarfMapping<77>;
196 def F28Dwarf : DwarfMapping<78>;
197 def F30Dwarf : DwarfMapping<79>;
199 def F25Dwarf : DwarfMapping<80>;
200 def F27Dwarf : DwarfMapping<81>;
201 def F29Dwarf : DwarfMapping<82>;
202 def F31Dwarf : DwarfMapping<83>;
204 // Upper 32 bits of one of the floating-point registers
205 class FPR32<bits<16> num, string n> : SystemZReg<n> {
206 let HWEncoding = num;
209 // One of the floating-point registers.
210 class FPR64<bits<16> num, string n, FPR32 high>
211 : SystemZRegWithSubregs<n, [high]> {
212 let HWEncoding = num;
213 let SubRegIndices = [subreg_h32];
216 // 8 pairs of FPR64s, with a one-register gap inbetween.
217 class FPR128<bits<16> num, string n, FPR64 low, FPR64 high>
218 : SystemZRegWithSubregs<n, [high, low]> {
219 let HWEncoding = num;
220 let SubRegIndices = [subreg_h64, subreg_l64];
221 let CoveredBySubRegs = 1;
224 // Floating-point registers. Registers 16-31 require the vector facility.
225 foreach I = 0-15 in {
226 def F#I#S : FPR32<I, "f"#I>;
227 def F#I#D : FPR64<I, "f"#I, !cast<FPR32>("F"#I#"S")>,
228 DwarfRegNum<[!cast<DwarfMapping>("F"#I#"Dwarf").Id]>;
230 foreach I = 16-31 in {
231 def F#I#S : FPR32<I, "v"#I>;
232 def F#I#D : FPR64<I, "v"#I, !cast<FPR32>("F"#I#"S")>,
233 DwarfRegNum<[!cast<DwarfMapping>("F"#I#"Dwarf").Id]>;
236 foreach I = [0, 1, 4, 5, 8, 9, 12, 13] in {
237 def F#I#Q : FPR128<I, "f"#I, !cast<FPR64>("F"#!add(I, 2)#"D"),
238 !cast<FPR64>("F"#I#"D")>;
241 // There's no store-multiple instruction for FPRs, so we're not fussy
242 // about the order in which call-saved registers are allocated.
243 defm FP32 : SystemZRegClass<"FP32", [f32], 32, (sequence "F%uS", 0, 15)>;
244 defm FP64 : SystemZRegClass<"FP64", [f64], 64, (sequence "F%uD", 0, 15)>;
245 defm FP128 : SystemZRegClass<"FP128", [f128], 128,
246 (add F0Q, F1Q, F4Q, F5Q, F8Q, F9Q, F12Q, F13Q)>;
248 //===----------------------------------------------------------------------===//
250 //===----------------------------------------------------------------------===//
252 // A full 128-bit vector register, with an FPR64 as its high part.
253 class VR128<bits<16> num, string n, FPR64 high>
254 : SystemZRegWithSubregs<n, [high]> {
255 let HWEncoding = num;
256 let SubRegIndices = [subreg_h64];
259 // Full vector registers.
260 foreach I = 0-31 in {
261 def V#I : VR128<I, "v"#I, !cast<FPR64>("F"#I#"D")>,
262 DwarfRegNum<[!cast<DwarfMapping>("F"#I#"Dwarf").Id]>;
265 // Class used to store 32-bit values in the first element of a vector
266 // register. f32 scalars are used for the WLEDB and WLDEB instructions.
267 defm VR32 : SystemZRegClass<"VR32", [f32, v4i8, v2i16], 32,
268 (add (sequence "F%uS", 0, 7),
269 (sequence "F%uS", 16, 31),
270 (sequence "F%uS", 8, 15))>;
272 // Class used to store 64-bit values in the upper half of a vector register.
273 // The vector facility also includes scalar f64 instructions that operate
274 // on the full vector register set.
275 defm VR64 : SystemZRegClass<"VR64", [f64, v8i8, v4i16, v2i32, v2f32], 64,
276 (add (sequence "F%uD", 0, 7),
277 (sequence "F%uD", 16, 31),
278 (sequence "F%uD", 8, 15))>;
280 // The subset of vector registers that can be used for floating-point
282 defm VF128 : SystemZRegClass<"VF128",
283 [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128,
284 (sequence "V%u", 0, 15)>;
286 // All vector registers.
287 defm VR128 : SystemZRegClass<"VR128",
288 [v16i8, v8i16, v4i32, v2i64, i128,
290 128, (add (sequence "V%u", 0, 7),
291 (sequence "V%u", 16, 31),
292 (sequence "V%u", 8, 15))>;
294 // Attaches a ValueType to a register operand, to make the instruction
295 // definitions easier.
296 class TypedReg<ValueType vtin, RegisterOperand opin> {
298 RegisterOperand op = opin;
301 def v32f : TypedReg<i32, VR32>;
302 def v32sb : TypedReg<f32, VR32>;
303 def v64g : TypedReg<i64, VR64>;
304 def v64db : TypedReg<f64, VR64>;
305 def v128b : TypedReg<v16i8, VR128>;
306 def v128h : TypedReg<v8i16, VR128>;
307 def v128f : TypedReg<v4i32, VR128>;
308 def v128g : TypedReg<v2i64, VR128>;
309 def v128q : TypedReg<i128, VR128>;
310 def v128sb : TypedReg<v4f32, VR128>;
311 def v128db : TypedReg<v2f64, VR128>;
312 def v128xb : TypedReg<f128, VR128>;
313 def v128any : TypedReg<untyped, VR128>;
315 //===----------------------------------------------------------------------===//
317 //===----------------------------------------------------------------------===//
319 // The 2-bit condition code field of the PSW. Every register named in an
320 // inline asm needs a class associated with it.
321 def CC : SystemZReg<"cc">;
322 let isAllocatable = 0, CopyCost = -1 in
323 def CCR : RegisterClass<"SystemZ", [i32], 32, (add CC)>;
325 // The floating-point control register.
326 // Note: We only model the current rounding modes and the IEEE masks.
327 // IEEE flags and DXC are not modeled here.
328 def FPC : SystemZReg<"fpc">;
329 let isAllocatable = 0 in
330 def FPCRegs : RegisterClass<"SystemZ", [i32], 32, (add FPC)>;
333 class ACR32<bits<16> num, string n> : SystemZReg<n> {
334 let HWEncoding = num;
336 foreach I = 0-15 in {
337 def A#I : ACR32<I, "a"#I>, DwarfRegNum<[!add(I, 48)]>;
339 defm AR32 : SystemZRegClass<"AR32", [i32], 32,
340 (add (sequence "A%u", 0, 15)), [], 0>;
342 // Control registers.
343 class CREG64<bits<16> num, string n> : SystemZReg<n> {
344 let HWEncoding = num;
346 foreach I = 0-15 in {
347 def C#I : CREG64<I, "c"#I>, DwarfRegNum<[!add(I, 32)]>;
349 defm CR64 : SystemZRegClass<"CR64", [i64], 64,
350 (add (sequence "C%u", 0, 15)), [], 0>;