181ad6265SDimitry Andric//===-- LoongArchRegisterInfo.td - LoongArch Register defs -*- tablegen -*-===//
281ad6265SDimitry Andric//
381ad6265SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric//
781ad6265SDimitry Andric//===----------------------------------------------------------------------===//
881ad6265SDimitry Andric
981ad6265SDimitry Andric//===----------------------------------------------------------------------===//
1081ad6265SDimitry Andric//  Declarations that describe the LoongArch register files
1181ad6265SDimitry Andric//===----------------------------------------------------------------------===//
1281ad6265SDimitry Andric
1381ad6265SDimitry Andriclet Namespace = "LoongArch" in {
1481ad6265SDimitry Andricclass LoongArchReg<bits<16> Enc, string n, list<string> alt = []>
1581ad6265SDimitry Andric    : Register<n> {
1681ad6265SDimitry Andric  let HWEncoding = Enc;
1781ad6265SDimitry Andric  let AltNames = alt;
1881ad6265SDimitry Andric}
1981ad6265SDimitry Andric
20*06c3fb27SDimitry Andricclass LoongArchRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs,
21*06c3fb27SDimitry Andric                              list<string> alt = []>
22*06c3fb27SDimitry Andric    : RegisterWithSubRegs<n, subregs> {
23*06c3fb27SDimitry Andric  let HWEncoding = Enc;
24*06c3fb27SDimitry Andric  let AltNames = alt;
25*06c3fb27SDimitry Andric}
26*06c3fb27SDimitry Andric
2781ad6265SDimitry Andricclass LoongArchReg32<bits<16> Enc, string n, list<string> alt = []>
2881ad6265SDimitry Andric    : Register<n> {
2981ad6265SDimitry Andric  let HWEncoding = Enc;
3081ad6265SDimitry Andric  let AltNames = alt;
3181ad6265SDimitry Andric}
3281ad6265SDimitry Andric
3381ad6265SDimitry Andricdef sub_32 : SubRegIndex<32>;
3481ad6265SDimitry Andricclass LoongArchReg64<LoongArchReg32 subreg>
35*06c3fb27SDimitry Andric    : LoongArchRegWithSubRegs<subreg.HWEncoding, subreg.AsmName, [subreg],
36*06c3fb27SDimitry Andric                              subreg.AltNames> {
3781ad6265SDimitry Andric  let SubRegIndices = [sub_32];
38*06c3fb27SDimitry Andric}
39*06c3fb27SDimitry Andric
40*06c3fb27SDimitry Andricdef sub_64 : SubRegIndex<64>;
41*06c3fb27SDimitry Andricclass LoongArchReg128<LoongArchReg64 subreg, string n>
42*06c3fb27SDimitry Andric    : LoongArchRegWithSubRegs<subreg.HWEncoding, n, [subreg]> {
43*06c3fb27SDimitry Andric  let SubRegIndices = [sub_64];
44*06c3fb27SDimitry Andric}
45*06c3fb27SDimitry Andric
46*06c3fb27SDimitry Andricdef sub_128 : SubRegIndex<128>;
47*06c3fb27SDimitry Andricclass LoongArchReg256<LoongArchReg128 subreg, string n>
48*06c3fb27SDimitry Andric    : LoongArchRegWithSubRegs<subreg.HWEncoding, n, [subreg]> {
49*06c3fb27SDimitry Andric  let SubRegIndices = [sub_128];
5081ad6265SDimitry Andric}
5181ad6265SDimitry Andric
5281ad6265SDimitry Andriclet FallbackRegAltNameIndex = NoRegAltName in
5381ad6265SDimitry Andricdef RegAliasName : RegAltNameIndex;
5481ad6265SDimitry Andric} // Namespace = "LoongArch"
5581ad6265SDimitry Andric
5681ad6265SDimitry Andric// Integer registers
5781ad6265SDimitry Andric
5881ad6265SDimitry Andriclet RegAltNameIndices = [RegAliasName] in {
59bdd1243dSDimitry Andric  let isConstant = true in
6081ad6265SDimitry Andric  def R0  : LoongArchReg<0,  "r0", ["zero"]>, DwarfRegNum<[0]>;
6181ad6265SDimitry Andric  def R1  : LoongArchReg<1,  "r1", ["ra"]>, DwarfRegNum<[1]>;
6281ad6265SDimitry Andric  def R2  : LoongArchReg<2,  "r2", ["tp"]>, DwarfRegNum<[2]>;
6381ad6265SDimitry Andric  def R3  : LoongArchReg<3,  "r3", ["sp"]>, DwarfRegNum<[3]>;
6481ad6265SDimitry Andric  def R4  : LoongArchReg<4,  "r4", ["a0"]>, DwarfRegNum<[4]>;
6581ad6265SDimitry Andric  def R5  : LoongArchReg<5,  "r5", ["a1"]>, DwarfRegNum<[5]>;
6681ad6265SDimitry Andric  def R6  : LoongArchReg<6,  "r6", ["a2"]>, DwarfRegNum<[6]>;
6781ad6265SDimitry Andric  def R7  : LoongArchReg<7,  "r7", ["a3"]>, DwarfRegNum<[7]>;
6881ad6265SDimitry Andric  def R8  : LoongArchReg<8,  "r8", ["a4"]>, DwarfRegNum<[8]>;
6981ad6265SDimitry Andric  def R9  : LoongArchReg<9,  "r9", ["a5"]>, DwarfRegNum<[9]>;
7081ad6265SDimitry Andric  def R10 : LoongArchReg<10, "r10", ["a6"]>, DwarfRegNum<[10]>;
7181ad6265SDimitry Andric  def R11 : LoongArchReg<11, "r11", ["a7"]>, DwarfRegNum<[11]>;
7281ad6265SDimitry Andric  def R12 : LoongArchReg<12, "r12", ["t0"]>, DwarfRegNum<[12]>;
7381ad6265SDimitry Andric  def R13 : LoongArchReg<13, "r13", ["t1"]>, DwarfRegNum<[13]>;
7481ad6265SDimitry Andric  def R14 : LoongArchReg<14, "r14", ["t2"]>, DwarfRegNum<[14]>;
7581ad6265SDimitry Andric  def R15 : LoongArchReg<15, "r15", ["t3"]>, DwarfRegNum<[15]>;
7681ad6265SDimitry Andric  def R16 : LoongArchReg<16, "r16", ["t4"]>, DwarfRegNum<[16]>;
7781ad6265SDimitry Andric  def R17 : LoongArchReg<17, "r17", ["t5"]>, DwarfRegNum<[17]>;
7881ad6265SDimitry Andric  def R18 : LoongArchReg<18, "r18", ["t6"]>, DwarfRegNum<[18]>;
7981ad6265SDimitry Andric  def R19 : LoongArchReg<19, "r19", ["t7"]>, DwarfRegNum<[19]>;
8081ad6265SDimitry Andric  def R20 : LoongArchReg<20, "r20", ["t8"]>, DwarfRegNum<[20]>;
8181ad6265SDimitry Andric  def R21 : LoongArchReg<21, "r21", [""]>, DwarfRegNum<[21]>;
8281ad6265SDimitry Andric  def R22 : LoongArchReg<22, "r22", ["fp", "s9"]>, DwarfRegNum<[22]>;
8381ad6265SDimitry Andric  def R23 : LoongArchReg<23, "r23", ["s0"]>, DwarfRegNum<[23]>;
8481ad6265SDimitry Andric  def R24 : LoongArchReg<24, "r24", ["s1"]>, DwarfRegNum<[24]>;
8581ad6265SDimitry Andric  def R25 : LoongArchReg<25, "r25", ["s2"]>, DwarfRegNum<[25]>;
8681ad6265SDimitry Andric  def R26 : LoongArchReg<26, "r26", ["s3"]>, DwarfRegNum<[26]>;
8781ad6265SDimitry Andric  def R27 : LoongArchReg<27, "r27", ["s4"]>, DwarfRegNum<[27]>;
8881ad6265SDimitry Andric  def R28 : LoongArchReg<28, "r28", ["s5"]>, DwarfRegNum<[28]>;
8981ad6265SDimitry Andric  def R29 : LoongArchReg<29, "r29", ["s6"]>, DwarfRegNum<[29]>;
9081ad6265SDimitry Andric  def R30 : LoongArchReg<30, "r30", ["s7"]>, DwarfRegNum<[30]>;
9181ad6265SDimitry Andric  def R31 : LoongArchReg<31, "r31", ["s8"]>, DwarfRegNum<[31]>;
9281ad6265SDimitry Andric} // RegAltNameIndices = [RegAliasName]
9381ad6265SDimitry Andric
9481ad6265SDimitry Andricdef GRLenVT : ValueTypeByHwMode<[LA32, LA64],
9581ad6265SDimitry Andric                                [i32,  i64]>;
9681ad6265SDimitry Andricdef GRLenRI : RegInfoByHwMode<
9781ad6265SDimitry Andric      [LA32,              LA64],
9881ad6265SDimitry Andric      [RegInfo<32,32,32>, RegInfo<64,64,64>]>;
9981ad6265SDimitry Andric
10081ad6265SDimitry Andric// The order of registers represents the preferred allocation sequence.
10181ad6265SDimitry Andric// Registers are listed in the order caller-save, callee-save, specials.
10281ad6265SDimitry Andricdef GPR : RegisterClass<"LoongArch", [GRLenVT], 32, (add
10381ad6265SDimitry Andric    // Argument registers (a0...a7)
10481ad6265SDimitry Andric    (sequence "R%u", 4, 11),
10581ad6265SDimitry Andric    // Temporary registers (t0...t8)
10681ad6265SDimitry Andric    (sequence "R%u", 12, 20),
10781ad6265SDimitry Andric    // Static register (s9/fp, s0...s8)
10881ad6265SDimitry Andric    (sequence "R%u", 22, 31),
10981ad6265SDimitry Andric    // Specials (r0, ra, tp, sp)
11081ad6265SDimitry Andric    (sequence "R%u", 0, 3),
11181ad6265SDimitry Andric    // Reserved (Non-allocatable)
11281ad6265SDimitry Andric    R21
11381ad6265SDimitry Andric  )> {
11481ad6265SDimitry Andric  let RegInfos = GRLenRI;
11581ad6265SDimitry Andric}
11681ad6265SDimitry Andric
117bdd1243dSDimitry Andric// GPR for indirect tail calls. We can't use callee-saved registers, as they are
118bdd1243dSDimitry Andric// restored to the saved value before the tail call, which would clobber a call
119bdd1243dSDimitry Andric// address.
120bdd1243dSDimitry Andricdef GPRT : RegisterClass<"LoongArch", [GRLenVT], 32, (add
121bdd1243dSDimitry Andric    // a0...a7, t0...t8
122bdd1243dSDimitry Andric    (sequence "R%u", 4, 20)
123bdd1243dSDimitry Andric  )> {
124bdd1243dSDimitry Andric  let RegInfos = GRLenRI;
125bdd1243dSDimitry Andric}
126bdd1243dSDimitry Andric
12781ad6265SDimitry Andric// Floating point registers
12881ad6265SDimitry Andric
12981ad6265SDimitry Andriclet RegAltNameIndices = [RegAliasName] in {
13081ad6265SDimitry Andric  def F0  : LoongArchReg32<0, "f0", ["fa0"]>, DwarfRegNum<[32]>;
13181ad6265SDimitry Andric  def F1  : LoongArchReg32<1, "f1", ["fa1"]>, DwarfRegNum<[33]>;
13281ad6265SDimitry Andric  def F2  : LoongArchReg32<2, "f2", ["fa2"]>, DwarfRegNum<[34]>;
13381ad6265SDimitry Andric  def F3  : LoongArchReg32<3, "f3", ["fa3"]>, DwarfRegNum<[35]>;
13481ad6265SDimitry Andric  def F4  : LoongArchReg32<4, "f4", ["fa4"]>, DwarfRegNum<[36]>;
13581ad6265SDimitry Andric  def F5  : LoongArchReg32<5, "f5", ["fa5"]>, DwarfRegNum<[37]>;
13681ad6265SDimitry Andric  def F6  : LoongArchReg32<6, "f6", ["fa6"]>, DwarfRegNum<[38]>;
13781ad6265SDimitry Andric  def F7  : LoongArchReg32<7, "f7", ["fa7"]>, DwarfRegNum<[39]>;
13881ad6265SDimitry Andric  def F8  : LoongArchReg32<8, "f8", ["ft0"]>, DwarfRegNum<[40]>;
13981ad6265SDimitry Andric  def F9  : LoongArchReg32<9, "f9", ["ft1"]>, DwarfRegNum<[41]>;
14081ad6265SDimitry Andric  def F10 : LoongArchReg32<10,"f10", ["ft2"]>, DwarfRegNum<[42]>;
14181ad6265SDimitry Andric  def F11 : LoongArchReg32<11,"f11", ["ft3"]>, DwarfRegNum<[43]>;
14281ad6265SDimitry Andric  def F12 : LoongArchReg32<12,"f12", ["ft4"]>, DwarfRegNum<[44]>;
14381ad6265SDimitry Andric  def F13 : LoongArchReg32<13,"f13", ["ft5"]>, DwarfRegNum<[45]>;
14481ad6265SDimitry Andric  def F14 : LoongArchReg32<14,"f14", ["ft6"]>, DwarfRegNum<[46]>;
14581ad6265SDimitry Andric  def F15 : LoongArchReg32<15,"f15", ["ft7"]>, DwarfRegNum<[47]>;
14681ad6265SDimitry Andric  def F16 : LoongArchReg32<16,"f16", ["ft8"]>, DwarfRegNum<[48]>;
14781ad6265SDimitry Andric  def F17 : LoongArchReg32<17,"f17", ["ft9"]>, DwarfRegNum<[49]>;
14881ad6265SDimitry Andric  def F18 : LoongArchReg32<18,"f18", ["ft10"]>, DwarfRegNum<[50]>;
14981ad6265SDimitry Andric  def F19 : LoongArchReg32<19,"f19", ["ft11"]>, DwarfRegNum<[51]>;
15081ad6265SDimitry Andric  def F20 : LoongArchReg32<20,"f20", ["ft12"]>, DwarfRegNum<[52]>;
15181ad6265SDimitry Andric  def F21 : LoongArchReg32<21,"f21", ["ft13"]>, DwarfRegNum<[53]>;
15281ad6265SDimitry Andric  def F22 : LoongArchReg32<22,"f22", ["ft14"]>, DwarfRegNum<[54]>;
15381ad6265SDimitry Andric  def F23 : LoongArchReg32<23,"f23", ["ft15"]>, DwarfRegNum<[55]>;
15481ad6265SDimitry Andric  def F24 : LoongArchReg32<24,"f24", ["fs0"]>, DwarfRegNum<[56]>;
15581ad6265SDimitry Andric  def F25 : LoongArchReg32<25,"f25", ["fs1"]>, DwarfRegNum<[57]>;
15681ad6265SDimitry Andric  def F26 : LoongArchReg32<26,"f26", ["fs2"]>, DwarfRegNum<[58]>;
15781ad6265SDimitry Andric  def F27 : LoongArchReg32<27,"f27", ["fs3"]>, DwarfRegNum<[59]>;
15881ad6265SDimitry Andric  def F28 : LoongArchReg32<28,"f28", ["fs4"]>, DwarfRegNum<[60]>;
15981ad6265SDimitry Andric  def F29 : LoongArchReg32<29,"f29", ["fs5"]>, DwarfRegNum<[61]>;
16081ad6265SDimitry Andric  def F30 : LoongArchReg32<30,"f30", ["fs6"]>, DwarfRegNum<[62]>;
16181ad6265SDimitry Andric  def F31 : LoongArchReg32<31,"f31", ["fs7"]>, DwarfRegNum<[63]>;
16281ad6265SDimitry Andric
16381ad6265SDimitry Andric  foreach I = 0-31 in {
16481ad6265SDimitry Andric    def F#I#_64 : LoongArchReg64<!cast<LoongArchReg32>("F"#I)>,
16581ad6265SDimitry Andric      DwarfRegNum<[!add(I, 32)]>;
16681ad6265SDimitry Andric  }
16781ad6265SDimitry Andric}
16881ad6265SDimitry Andric
16981ad6265SDimitry Andric// The order of registers represents the preferred allocation sequence.
17081ad6265SDimitry Andricdef FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>;
17181ad6265SDimitry Andricdef FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>;
17281ad6265SDimitry Andric
17381ad6265SDimitry Andric// Condition flag registers
17481ad6265SDimitry Andric
17581ad6265SDimitry Andricforeach I = 0-7 in
17681ad6265SDimitry Andricdef FCC#I : LoongArchReg<I, "fcc"#I>;
17781ad6265SDimitry Andric
17881ad6265SDimitry Andricdef CFR : RegisterClass<"LoongArch", [GRLenVT], 32, (sequence "FCC%u", 0, 7)> {
17981ad6265SDimitry Andric  let RegInfos = GRLenRI;
18081ad6265SDimitry Andric}
18181ad6265SDimitry Andric
18281ad6265SDimitry Andric// Control and status registers
18381ad6265SDimitry Andric
18481ad6265SDimitry Andricforeach I = 0-3 in
18581ad6265SDimitry Andricdef FCSR#I : LoongArchReg<I, "fcsr"#I>;
18681ad6265SDimitry Andric
18781ad6265SDimitry Andriclet isAllocatable = false in
18881ad6265SDimitry Andricdef FCSR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCSR%u", 0, 3)>;
189*06c3fb27SDimitry Andric
190*06c3fb27SDimitry Andric// LSX registers
191*06c3fb27SDimitry Andric
192*06c3fb27SDimitry Andricforeach I = 0-31 in
193*06c3fb27SDimitry Andricdef VR#I : LoongArchReg128<!cast<LoongArchReg64>("F"#I#"_64"), "vr"#I>,
194*06c3fb27SDimitry Andric           DwarfRegAlias<!cast<LoongArchReg64>("F"#I#"_64")>;
195*06c3fb27SDimitry Andric
196*06c3fb27SDimitry Andricdef LSX128 : RegisterClass<"LoongArch",
197*06c3fb27SDimitry Andric                           [v4f32, v2f64, v16i8, v8i16, v4i32, v2i64],
198*06c3fb27SDimitry Andric                           128, (sequence "VR%u", 0, 31)>;
199*06c3fb27SDimitry Andric
200*06c3fb27SDimitry Andric// LASX registers
201*06c3fb27SDimitry Andric
202*06c3fb27SDimitry Andricforeach I = 0-31 in
203*06c3fb27SDimitry Andricdef XR#I : LoongArchReg256<!cast<LoongArchReg128>("VR"#I), "xr"#I>,
204*06c3fb27SDimitry Andric           DwarfRegAlias<!cast<LoongArchReg128>("VR"#I)>;
205*06c3fb27SDimitry Andric
206*06c3fb27SDimitry Andricdef LASX256 : RegisterClass<"LoongArch",
207*06c3fb27SDimitry Andric                            [v8f32, v4f64, v32i8, v16i16, v8i32, v4i64],
208*06c3fb27SDimitry Andric                            256, (sequence "XR%u", 0, 31)>;
209*06c3fb27SDimitry Andric
210*06c3fb27SDimitry Andric// Scratchpad registers
211*06c3fb27SDimitry Andric
212*06c3fb27SDimitry Andricforeach I = 0-3 in
213*06c3fb27SDimitry Andricdef SCR#I : LoongArchReg<I, "scr"#I>;
214*06c3fb27SDimitry Andric
215*06c3fb27SDimitry Andriclet isAllocatable = false, RegInfos = GRLenRI in
216*06c3fb27SDimitry Andricdef SCR : RegisterClass<"LoongArch", [GRLenVT], 32, (sequence "SCR%u", 0, 3)>;
217