xref: /llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td (revision 21ef17c626456496a18e2a078a11d8eccf26ee31)
1//===-- LoongArchRegisterInfo.td - LoongArch Register defs -*- tablegen -*-===//
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//===----------------------------------------------------------------------===//
10//  Declarations that describe the LoongArch register files
11//===----------------------------------------------------------------------===//
12
13let Namespace = "LoongArch" in {
14class LoongArchReg<bits<16> Enc, string n, list<string> alt = []>
15    : Register<n> {
16  let HWEncoding = Enc;
17  let AltNames = alt;
18}
19
20class LoongArchRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs,
21                              list<string> alt = []>
22    : RegisterWithSubRegs<n, subregs> {
23  let HWEncoding = Enc;
24  let AltNames = alt;
25}
26
27class LoongArchReg32<bits<16> Enc, string n, list<string> alt = []>
28    : Register<n> {
29  let HWEncoding = Enc;
30  let AltNames = alt;
31}
32
33def sub_32 : SubRegIndex<32>;
34class LoongArchReg64<LoongArchReg32 subreg>
35    : LoongArchRegWithSubRegs<subreg.HWEncoding, subreg.AsmName, [subreg],
36                              subreg.AltNames> {
37  let SubRegIndices = [sub_32];
38}
39
40def sub_64 : SubRegIndex<64>;
41class LoongArchReg128<LoongArchReg64 subreg, string n>
42    : LoongArchRegWithSubRegs<subreg.HWEncoding, n, [subreg]> {
43  let SubRegIndices = [sub_64];
44}
45
46def sub_128 : SubRegIndex<128>;
47class LoongArchReg256<LoongArchReg128 subreg, string n>
48    : LoongArchRegWithSubRegs<subreg.HWEncoding, n, [subreg]> {
49  let SubRegIndices = [sub_128];
50}
51
52let FallbackRegAltNameIndex = NoRegAltName in
53def RegAliasName : RegAltNameIndex;
54} // Namespace = "LoongArch"
55
56// Integer registers
57
58let RegAltNameIndices = [RegAliasName] in {
59  let isConstant = true in
60  def R0  : LoongArchReg<0,  "r0", ["zero"]>, DwarfRegNum<[0]>;
61  def R1  : LoongArchReg<1,  "r1", ["ra"]>, DwarfRegNum<[1]>;
62  def R2  : LoongArchReg<2,  "r2", ["tp"]>, DwarfRegNum<[2]>;
63  def R3  : LoongArchReg<3,  "r3", ["sp"]>, DwarfRegNum<[3]>;
64  def R4  : LoongArchReg<4,  "r4", ["a0"]>, DwarfRegNum<[4]>;
65  def R5  : LoongArchReg<5,  "r5", ["a1"]>, DwarfRegNum<[5]>;
66  def R6  : LoongArchReg<6,  "r6", ["a2"]>, DwarfRegNum<[6]>;
67  def R7  : LoongArchReg<7,  "r7", ["a3"]>, DwarfRegNum<[7]>;
68  def R8  : LoongArchReg<8,  "r8", ["a4"]>, DwarfRegNum<[8]>;
69  def R9  : LoongArchReg<9,  "r9", ["a5"]>, DwarfRegNum<[9]>;
70  def R10 : LoongArchReg<10, "r10", ["a6"]>, DwarfRegNum<[10]>;
71  def R11 : LoongArchReg<11, "r11", ["a7"]>, DwarfRegNum<[11]>;
72  def R12 : LoongArchReg<12, "r12", ["t0"]>, DwarfRegNum<[12]>;
73  def R13 : LoongArchReg<13, "r13", ["t1"]>, DwarfRegNum<[13]>;
74  def R14 : LoongArchReg<14, "r14", ["t2"]>, DwarfRegNum<[14]>;
75  def R15 : LoongArchReg<15, "r15", ["t3"]>, DwarfRegNum<[15]>;
76  def R16 : LoongArchReg<16, "r16", ["t4"]>, DwarfRegNum<[16]>;
77  def R17 : LoongArchReg<17, "r17", ["t5"]>, DwarfRegNum<[17]>;
78  def R18 : LoongArchReg<18, "r18", ["t6"]>, DwarfRegNum<[18]>;
79  def R19 : LoongArchReg<19, "r19", ["t7"]>, DwarfRegNum<[19]>;
80  def R20 : LoongArchReg<20, "r20", ["t8"]>, DwarfRegNum<[20]>;
81  def R21 : LoongArchReg<21, "r21", [""]>, DwarfRegNum<[21]>;
82  def R22 : LoongArchReg<22, "r22", ["fp", "s9"]>, DwarfRegNum<[22]>;
83  def R23 : LoongArchReg<23, "r23", ["s0"]>, DwarfRegNum<[23]>;
84  def R24 : LoongArchReg<24, "r24", ["s1"]>, DwarfRegNum<[24]>;
85  def R25 : LoongArchReg<25, "r25", ["s2"]>, DwarfRegNum<[25]>;
86  def R26 : LoongArchReg<26, "r26", ["s3"]>, DwarfRegNum<[26]>;
87  def R27 : LoongArchReg<27, "r27", ["s4"]>, DwarfRegNum<[27]>;
88  def R28 : LoongArchReg<28, "r28", ["s5"]>, DwarfRegNum<[28]>;
89  def R29 : LoongArchReg<29, "r29", ["s6"]>, DwarfRegNum<[29]>;
90  def R30 : LoongArchReg<30, "r30", ["s7"]>, DwarfRegNum<[30]>;
91  def R31 : LoongArchReg<31, "r31", ["s8"]>, DwarfRegNum<[31]>;
92} // RegAltNameIndices = [RegAliasName]
93
94def GRLenVT : ValueTypeByHwMode<[LA32, LA64],
95                                [i32,  i64]>;
96def GRLenRI : RegInfoByHwMode<
97      [LA32,              LA64],
98      [RegInfo<32,32,32>, RegInfo<64,64,64>]>;
99
100class GPRRegisterClass<dag regList>
101    : RegisterClass<"LoongArch", [GRLenVT], 32, regList> {
102  let RegInfos = GRLenRI;
103}
104
105// The order of registers represents the preferred allocation sequence.
106// Registers are listed in the order caller-save, callee-save, specials.
107def GPR : GPRRegisterClass<(add // Argument registers (a0...a7)
108                                (sequence "R%u", 4, 11),
109                                // Temporary registers (t0...t8)
110                                (sequence "R%u", 12, 20),
111                                // Static register (s9/fp, s0...s8)
112                                (sequence "R%u", 22, 31),
113                                // Specials (r0, ra, tp, sp)
114                                (sequence "R%u", 0, 3),
115                                // Reserved (Non-allocatable)
116                                R21)>;
117
118// GPR for indirect tail calls. We can't use callee-saved registers, as they are
119// restored to the saved value before the tail call, which would clobber a call
120// address.
121def GPRT : GPRRegisterClass<(add // a0...a7, t0...t8
122                                 (sequence "R%u", 4, 20))>;
123
124// Don't use R1 for JR since that micro-architecture unconditionally treats a
125// "jr $ra" as "return from subroutine", hence doing "jr $ra" would interfere
126// with both subroutine return prediction and the more general indirect branch
127// prediction.
128def GPRJR : GPRRegisterClass<(sub GPR, R1)>;
129
130// Floating point registers
131
132let RegAltNameIndices = [RegAliasName] in {
133  def F0  : LoongArchReg32<0, "f0", ["fa0"]>, DwarfRegNum<[32]>;
134  def F1  : LoongArchReg32<1, "f1", ["fa1"]>, DwarfRegNum<[33]>;
135  def F2  : LoongArchReg32<2, "f2", ["fa2"]>, DwarfRegNum<[34]>;
136  def F3  : LoongArchReg32<3, "f3", ["fa3"]>, DwarfRegNum<[35]>;
137  def F4  : LoongArchReg32<4, "f4", ["fa4"]>, DwarfRegNum<[36]>;
138  def F5  : LoongArchReg32<5, "f5", ["fa5"]>, DwarfRegNum<[37]>;
139  def F6  : LoongArchReg32<6, "f6", ["fa6"]>, DwarfRegNum<[38]>;
140  def F7  : LoongArchReg32<7, "f7", ["fa7"]>, DwarfRegNum<[39]>;
141  def F8  : LoongArchReg32<8, "f8", ["ft0"]>, DwarfRegNum<[40]>;
142  def F9  : LoongArchReg32<9, "f9", ["ft1"]>, DwarfRegNum<[41]>;
143  def F10 : LoongArchReg32<10,"f10", ["ft2"]>, DwarfRegNum<[42]>;
144  def F11 : LoongArchReg32<11,"f11", ["ft3"]>, DwarfRegNum<[43]>;
145  def F12 : LoongArchReg32<12,"f12", ["ft4"]>, DwarfRegNum<[44]>;
146  def F13 : LoongArchReg32<13,"f13", ["ft5"]>, DwarfRegNum<[45]>;
147  def F14 : LoongArchReg32<14,"f14", ["ft6"]>, DwarfRegNum<[46]>;
148  def F15 : LoongArchReg32<15,"f15", ["ft7"]>, DwarfRegNum<[47]>;
149  def F16 : LoongArchReg32<16,"f16", ["ft8"]>, DwarfRegNum<[48]>;
150  def F17 : LoongArchReg32<17,"f17", ["ft9"]>, DwarfRegNum<[49]>;
151  def F18 : LoongArchReg32<18,"f18", ["ft10"]>, DwarfRegNum<[50]>;
152  def F19 : LoongArchReg32<19,"f19", ["ft11"]>, DwarfRegNum<[51]>;
153  def F20 : LoongArchReg32<20,"f20", ["ft12"]>, DwarfRegNum<[52]>;
154  def F21 : LoongArchReg32<21,"f21", ["ft13"]>, DwarfRegNum<[53]>;
155  def F22 : LoongArchReg32<22,"f22", ["ft14"]>, DwarfRegNum<[54]>;
156  def F23 : LoongArchReg32<23,"f23", ["ft15"]>, DwarfRegNum<[55]>;
157  def F24 : LoongArchReg32<24,"f24", ["fs0"]>, DwarfRegNum<[56]>;
158  def F25 : LoongArchReg32<25,"f25", ["fs1"]>, DwarfRegNum<[57]>;
159  def F26 : LoongArchReg32<26,"f26", ["fs2"]>, DwarfRegNum<[58]>;
160  def F27 : LoongArchReg32<27,"f27", ["fs3"]>, DwarfRegNum<[59]>;
161  def F28 : LoongArchReg32<28,"f28", ["fs4"]>, DwarfRegNum<[60]>;
162  def F29 : LoongArchReg32<29,"f29", ["fs5"]>, DwarfRegNum<[61]>;
163  def F30 : LoongArchReg32<30,"f30", ["fs6"]>, DwarfRegNum<[62]>;
164  def F31 : LoongArchReg32<31,"f31", ["fs7"]>, DwarfRegNum<[63]>;
165
166  foreach I = 0-31 in {
167    def F#I#_64 : LoongArchReg64<!cast<LoongArchReg32>("F"#I)>,
168      DwarfRegNum<[!add(I, 32)]>;
169  }
170}
171
172// The order of registers represents the preferred allocation sequence.
173def FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>;
174def FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>;
175
176// Condition flag registers
177
178foreach I = 0-7 in
179def FCC#I : LoongArchReg<I, "fcc"#I>;
180
181def CFR : RegisterClass<"LoongArch", [GRLenVT], 32, (sequence "FCC%u", 0, 7)> {
182  let RegInfos = GRLenRI;
183}
184
185// Control and status registers
186
187foreach I = 0-3 in
188def FCSR#I : LoongArchReg<I, "fcsr"#I>;
189
190let isAllocatable = false in
191def FCSR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCSR%u", 0, 3)>;
192
193// LSX registers
194
195foreach I = 0-31 in
196def VR#I : LoongArchReg128<!cast<LoongArchReg64>("F"#I#"_64"), "vr"#I>,
197           DwarfRegAlias<!cast<LoongArchReg64>("F"#I#"_64")>;
198
199def LSX128 : RegisterClass<"LoongArch",
200                           [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64],
201                           128, (sequence "VR%u", 0, 31)>;
202
203// LASX registers
204
205foreach I = 0-31 in
206def XR#I : LoongArchReg256<!cast<LoongArchReg128>("VR"#I), "xr"#I>,
207           DwarfRegAlias<!cast<LoongArchReg128>("VR"#I)>;
208
209def LASX256 : RegisterClass<"LoongArch",
210                            [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64],
211                            256, (sequence "XR%u", 0, 31)>;
212
213// Scratchpad registers
214
215foreach I = 0-3 in
216def SCR#I : LoongArchReg<I, "scr"#I>;
217
218let isAllocatable = false, RegInfos = GRLenRI in
219def SCR : RegisterClass<"LoongArch", [GRLenVT], 32, (sequence "SCR%u", 0, 3)>;
220