1249259Sdim//===- AArch64RegisterInfo.td - ARM Register defs ----------*- tablegen -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim//  This file contains declarations that describe the AArch64 register file
11249259Sdim//
12249259Sdim//===----------------------------------------------------------------------===//
13249259Sdim
14249259Sdimlet Namespace = "AArch64" in {
15263508Sdimdef sub_128 : SubRegIndex<128>;
16263508Sdimdef sub_64 : SubRegIndex<64>;
17263508Sdimdef sub_32 : SubRegIndex<32>;
18263508Sdimdef sub_16 : SubRegIndex<16>;
19263508Sdimdef sub_8  : SubRegIndex<8>;
20249259Sdim
21263508Sdim// Note: Code depends on these having consecutive numbers.
22263508Sdimdef qqsub : SubRegIndex<256, 256>;
23263508Sdim
24263508Sdimdef qsub_0 : SubRegIndex<128>;
25263508Sdimdef qsub_1 : SubRegIndex<128, 128>;
26263508Sdimdef qsub_2 : ComposedSubRegIndex<qqsub, qsub_0>;
27263508Sdimdef qsub_3 : ComposedSubRegIndex<qqsub, qsub_1>;
28263508Sdim
29263508Sdimdef dsub_0 : SubRegIndex<64>;
30263508Sdimdef dsub_1 : SubRegIndex<64, 64>;
31263508Sdimdef dsub_2 : ComposedSubRegIndex<qsub_1, dsub_0>;
32263508Sdimdef dsub_3 : ComposedSubRegIndex<qsub_1, dsub_1>;
33263508Sdimdef dsub_4 : ComposedSubRegIndex<qsub_2, dsub_0>;
34249259Sdim}
35249259Sdim
36249259Sdim// Registers are identified with 5-bit ID numbers.
37249259Sdimclass AArch64Reg<bits<16> enc, string n> : Register<n> {
38249259Sdim  let HWEncoding = enc;
39249259Sdim  let Namespace = "AArch64";
40249259Sdim}
41249259Sdim
42249259Sdimclass AArch64RegWithSubs<bits<16> enc, string n, list<Register> subregs = [],
43249259Sdim                         list<SubRegIndex> inds = []>
44249259Sdim      : AArch64Reg<enc, n> {
45249259Sdim  let SubRegs = subregs;
46249259Sdim  let SubRegIndices = inds;
47249259Sdim}
48249259Sdim
49249259Sdim//===----------------------------------------------------------------------===//
50249259Sdim//  Integer registers: w0-w30, wzr, wsp, x0-x30, xzr, sp
51249259Sdim//===----------------------------------------------------------------------===//
52249259Sdim
53249259Sdimforeach Index = 0-30 in {
54249259Sdim  def W#Index : AArch64Reg< Index, "w"#Index>, DwarfRegNum<[Index]>;
55249259Sdim}
56249259Sdim
57249259Sdimdef WSP : AArch64Reg<31, "wsp">, DwarfRegNum<[31]>;
58249259Sdimdef WZR : AArch64Reg<31, "wzr">;
59249259Sdim
60249259Sdim// Could be combined with previous loop, but this way leaves w and x registers
61249259Sdim// consecutive as LLVM register numbers, which makes for easier debugging.
62249259Sdimforeach Index = 0-30 in {
63249259Sdim  def X#Index : AArch64RegWithSubs<Index, "x"#Index,
64249259Sdim                                   [!cast<Register>("W"#Index)], [sub_32]>,
65249259Sdim                DwarfRegNum<[Index]>;
66249259Sdim}
67249259Sdim
68249259Sdimdef XSP : AArch64RegWithSubs<31, "sp", [WSP], [sub_32]>, DwarfRegNum<[31]>;
69249259Sdimdef XZR : AArch64RegWithSubs<31, "xzr", [WZR], [sub_32]>;
70249259Sdim
71249259Sdim// Most instructions treat register 31 as zero for reads and a black-hole for
72249259Sdim// writes.
73249259Sdim
74249259Sdim// Note that the order of registers is important for the Disassembler here:
75249259Sdim// tablegen uses it to form MCRegisterClass::getRegister, which we assume can
76249259Sdim// take an encoding value.
77249259Sdimdef GPR32 : RegisterClass<"AArch64", [i32], 32,
78249259Sdim                          (add (sequence "W%u", 0, 30), WZR)> {
79249259Sdim}
80249259Sdim
81249259Sdimdef GPR64 : RegisterClass<"AArch64", [i64], 64,
82249259Sdim                          (add (sequence "X%u", 0, 30), XZR)> {
83249259Sdim}
84249259Sdim
85249259Sdimdef GPR32nowzr : RegisterClass<"AArch64", [i32], 32,
86249259Sdim                               (sequence "W%u", 0, 30)> {
87249259Sdim}
88249259Sdim
89249259Sdimdef GPR64noxzr : RegisterClass<"AArch64", [i64], 64,
90249259Sdim                               (sequence "X%u", 0, 30)> {
91249259Sdim}
92249259Sdim
93249259Sdim// For tail calls, we can't use callee-saved registers or the structure-return
94249259Sdim// register, as they are supposed to be live across function calls and may be
95249259Sdim// clobbered by the epilogue.
96249259Sdimdef tcGPR64 : RegisterClass<"AArch64", [i64], 64,
97249259Sdim                            (add (sequence "X%u", 0, 7),
98249259Sdim                                 (sequence "X%u", 9, 18))> {
99249259Sdim}
100249259Sdim
101249259Sdim
102249259Sdim// Certain addressing-useful instructions accept sp directly. Again the order of
103249259Sdim// registers is important to the Disassembler.
104249259Sdimdef GPR32wsp : RegisterClass<"AArch64", [i32], 32,
105249259Sdim                             (add (sequence "W%u", 0, 30), WSP)> {
106249259Sdim}
107249259Sdim
108249259Sdimdef GPR64xsp : RegisterClass<"AArch64", [i64], 64,
109249259Sdim                             (add (sequence "X%u", 0, 30), XSP)> {
110249259Sdim}
111249259Sdim
112249259Sdim// Some aliases *only* apply to SP (e.g. MOV uses different encoding for SP and
113249259Sdim// non-SP variants). We can't use a bare register in those patterns because
114249259Sdim// TableGen doesn't like it, so we need a class containing just stack registers
115249259Sdimdef Rxsp : RegisterClass<"AArch64", [i64], 64,
116249259Sdim                         (add XSP)> {
117249259Sdim}
118249259Sdim
119249259Sdimdef Rwsp : RegisterClass<"AArch64", [i32], 32,
120249259Sdim                         (add WSP)> {
121249259Sdim}
122249259Sdim
123249259Sdim//===----------------------------------------------------------------------===//
124249259Sdim//  Scalar registers in the vector unit:
125249259Sdim//  b0-b31, h0-h31, s0-s31, d0-d31, q0-q31
126249259Sdim//===----------------------------------------------------------------------===//
127249259Sdim
128249259Sdimforeach Index = 0-31 in {
129249259Sdim  def B # Index : AArch64Reg< Index, "b" # Index>,
130249259Sdim                  DwarfRegNum<[!add(Index, 64)]>;
131249259Sdim
132249259Sdim  def H # Index : AArch64RegWithSubs<Index, "h" # Index,
133249259Sdim                                     [!cast<Register>("B" # Index)], [sub_8]>,
134249259Sdim                  DwarfRegNum<[!add(Index, 64)]>;
135249259Sdim
136249259Sdim  def S # Index : AArch64RegWithSubs<Index, "s" # Index,
137249259Sdim                                     [!cast<Register>("H" # Index)], [sub_16]>,
138249259Sdim                  DwarfRegNum<[!add(Index, 64)]>;
139249259Sdim
140249259Sdim  def D # Index : AArch64RegWithSubs<Index, "d" # Index,
141249259Sdim                                     [!cast<Register>("S" # Index)], [sub_32]>,
142249259Sdim                  DwarfRegNum<[!add(Index, 64)]>;
143249259Sdim
144249259Sdim  def Q # Index : AArch64RegWithSubs<Index, "q" # Index,
145249259Sdim                                     [!cast<Register>("D" # Index)], [sub_64]>,
146249259Sdim                  DwarfRegNum<[!add(Index, 64)]>;
147249259Sdim}
148249259Sdim
149249259Sdim
150263508Sdimdef FPR8 : RegisterClass<"AArch64", [i8, v1i8], 8,
151249259Sdim                          (sequence "B%u", 0, 31)> {
152249259Sdim}
153249259Sdim
154263508Sdimdef FPR16 : RegisterClass<"AArch64", [f16, v1i16], 16,
155249259Sdim                          (sequence "H%u", 0, 31)> {
156249259Sdim}
157249259Sdim
158263508Sdimdef FPR32 : RegisterClass<"AArch64", [f32, v1i32, v1f32], 32,
159249259Sdim                          (sequence "S%u", 0, 31)> {
160249259Sdim}
161249259Sdim
162263508Sdimdef FPR64 : RegisterClass<"AArch64",
163263508Sdim                          [f64, v2f32, v2i32, v4i16, v8i8, v1i64, v1f64],
164263508Sdim                          64, (sequence "D%u", 0, 31)>;
165249259Sdim
166263508Sdimdef FPR128 : RegisterClass<"AArch64",
167263508Sdim                           [f128, v2f64, v2i64, v4f32, v4i32, v8i16, v16i8],
168263508Sdim                           128, (sequence "Q%u", 0, 31)>;
169249259Sdim
170263508Sdimdef FPR64Lo : RegisterClass<"AArch64",
171263508Sdim                            [f64, v2f32, v2i32, v4i16, v8i8, v1i64, v1f64],
172263508Sdim                            64, (sequence "D%u", 0, 15)>;
173249259Sdim
174263508Sdimdef FPR128Lo : RegisterClass<"AArch64",
175263508Sdim                             [f128, v2f64, v2i64, v4f32, v4i32, v8i16, v16i8],
176263508Sdim                             128, (sequence "Q%u", 0, 15)>;
177263508Sdim
178249259Sdim//===----------------------------------------------------------------------===//
179249259Sdim//  Vector registers:
180249259Sdim//===----------------------------------------------------------------------===//
181249259Sdim
182263508Sdimdef VPR64AsmOperand : AsmOperandClass {
183263508Sdim  let Name = "VPR";
184263508Sdim  let PredicateMethod = "isReg";
185263508Sdim  let RenderMethod = "addRegOperands";
186249259Sdim}
187249259Sdim
188263508Sdimdef VPR64 : RegisterOperand<FPR64, "printVPRRegister">;
189249259Sdim
190263508Sdimdef VPR128 : RegisterOperand<FPR128, "printVPRRegister">;
191249259Sdim
192263508Sdimdef VPR64Lo : RegisterOperand<FPR64Lo, "printVPRRegister">;
193263508Sdim
194263508Sdimdef VPR128Lo : RegisterOperand<FPR128Lo, "printVPRRegister">;
195263508Sdim
196249259Sdim// Flags register
197249259Sdimdef NZCV : Register<"nzcv"> {
198249259Sdim  let Namespace = "AArch64";
199249259Sdim}
200249259Sdim
201249259Sdimdef FlagClass : RegisterClass<"AArch64", [i32], 32, (add NZCV)> {
202249259Sdim  let CopyCost = -1;
203249259Sdim  let isAllocatable = 0;
204249259Sdim}
205263508Sdim
206263508Sdim//===----------------------------------------------------------------------===//
207263508Sdim//  Consecutive vector registers
208263508Sdim//===----------------------------------------------------------------------===//
209263508Sdim// 2 Consecutive 64-bit registers: D0_D1, D1_D2, ..., D30_D31
210263508Sdimdef Tuples2D : RegisterTuples<[dsub_0, dsub_1],
211263508Sdim                              [(rotl FPR64, 0), (rotl FPR64, 1)]>;
212263508Sdim                              
213263508Sdim// 3 Consecutive 64-bit registers: D0_D1_D2, ..., D31_D0_D1
214263508Sdimdef Tuples3D : RegisterTuples<[dsub_0, dsub_1, dsub_2],
215263508Sdim                              [(rotl FPR64, 0), (rotl FPR64, 1),
216263508Sdim                               (rotl FPR64, 2)]>;
217263508Sdim                               
218263508Sdim// 4 Consecutive 64-bit registers: D0_D1_D2_D3, ..., D31_D0_D1_D2
219263508Sdimdef Tuples4D : RegisterTuples<[dsub_0, dsub_1, dsub_2, dsub_3],
220263508Sdim                              [(rotl FPR64, 0), (rotl FPR64, 1),
221263508Sdim                               (rotl FPR64, 2), (rotl FPR64, 3)]>;
222263508Sdim
223263508Sdim// 2 Consecutive 128-bit registers: Q0_Q1, Q1_Q2, ..., Q30_Q31
224263508Sdimdef Tuples2Q : RegisterTuples<[qsub_0, qsub_1],
225263508Sdim                              [(rotl FPR128, 0), (rotl FPR128, 1)]>;
226263508Sdim
227263508Sdim// 3 Consecutive 128-bit registers: Q0_Q1_Q2, ..., Q31_Q0_Q1
228263508Sdimdef Tuples3Q : RegisterTuples<[qsub_0, qsub_1, qsub_2],
229263508Sdim                              [(rotl FPR128, 0), (rotl FPR128, 1),
230263508Sdim                               (rotl FPR128, 2)]>;
231263508Sdim                               
232263508Sdim// 4 Consecutive 128-bit registers: Q0_Q1_Q2_Q3, ..., Q31_Q0_Q1_Q2
233263508Sdimdef Tuples4Q : RegisterTuples<[qsub_0, qsub_1, qsub_2, qsub_3],
234263508Sdim                              [(rotl FPR128, 0), (rotl FPR128, 1),
235263508Sdim                               (rotl FPR128, 2), (rotl FPR128, 3)]>;
236263508Sdim
237263508Sdim// The followings are super register classes to model 2/3/4 consecutive
238263508Sdim// 64-bit/128-bit registers.
239263508Sdim
240263508Sdimdef DPair : RegisterClass<"AArch64", [v2i64], 64, (add Tuples2D)>;
241263508Sdim
242263508Sdimdef DTriple : RegisterClass<"AArch64", [untyped], 64, (add Tuples3D)> {
243263508Sdim  let Size = 192; // 3 x 64 bits, we have no predefined type of that size.
244263508Sdim}
245263508Sdim
246263508Sdimdef DQuad : RegisterClass<"AArch64", [v4i64], 64, (add Tuples4D)>;
247263508Sdim
248263508Sdimdef QPair : RegisterClass<"AArch64", [v4i64], 128, (add Tuples2Q)>;
249263508Sdim
250263508Sdimdef QTriple : RegisterClass<"AArch64", [untyped], 128, (add Tuples3Q)> {
251263508Sdim  let Size = 384; // 3 x 128 bits, we have no predefined type of that size.
252263508Sdim}
253263508Sdim
254263508Sdimdef QQuad : RegisterClass<"AArch64", [v8i64], 128, (add Tuples4Q)>;
255263508Sdim
256263508Sdim
257263508Sdim// The followings are vector list operands
258263508Sdimmulticlass VectorList_operands<string PREFIX, string LAYOUT, int Count,
259263508Sdim                               RegisterClass RegList> {
260263508Sdim  def _asmoperand : AsmOperandClass {
261263508Sdim    let Name = PREFIX # LAYOUT # Count;
262263508Sdim    let RenderMethod = "addVectorListOperands";
263263508Sdim    let PredicateMethod = 
264263508Sdim        "isVectorList<A64Layout::VL_" # LAYOUT # ", " # Count # ">";
265263508Sdim    let ParserMethod = "ParseVectorList";
266263508Sdim  }
267263508Sdim
268263508Sdim  def _operand : RegisterOperand<RegList,
269263508Sdim        "printVectorList<A64Layout::VL_" # LAYOUT # ", " # Count # ">"> {
270263508Sdim    let ParserMatchClass =
271263508Sdim      !cast<AsmOperandClass>(PREFIX # LAYOUT # "_asmoperand");
272263508Sdim  }
273263508Sdim}
274263508Sdim
275263508Sdimmulticlass VectorList_BHSD<string PREFIX, int Count, RegisterClass DRegList,
276263508Sdim                           RegisterClass QRegList> {
277263508Sdim  defm 8B : VectorList_operands<PREFIX, "8B", Count, DRegList>;
278263508Sdim  defm 4H : VectorList_operands<PREFIX, "4H", Count, DRegList>;
279263508Sdim  defm 2S : VectorList_operands<PREFIX, "2S", Count, DRegList>;
280263508Sdim  defm 1D : VectorList_operands<PREFIX, "1D", Count, DRegList>;
281263508Sdim  defm 16B : VectorList_operands<PREFIX, "16B", Count, QRegList>;
282263508Sdim  defm 8H : VectorList_operands<PREFIX, "8H", Count, QRegList>;
283263508Sdim  defm 4S : VectorList_operands<PREFIX, "4S", Count, QRegList>;
284263508Sdim  defm 2D : VectorList_operands<PREFIX, "2D", Count, QRegList>;
285263508Sdim}
286263508Sdim
287263508Sdim// Vector list operand with 1/2/3/4 registers: VOne8B_operand,..., VQuad2D_operand
288263508Sdimdefm VOne : VectorList_BHSD<"VOne", 1, FPR64, FPR128>;
289263508Sdimdefm VPair : VectorList_BHSD<"VPair", 2, DPair, QPair>;
290263508Sdimdefm VTriple : VectorList_BHSD<"VTriple", 3, DTriple, QTriple>;
291263508Sdimdefm VQuad : VectorList_BHSD<"VQuad", 4, DQuad, QQuad>;