AArch64RegisterInfo.td revision 151dfc7d7ff6406a471058fcd142018a10b0c479
1//===- AArch64RegisterInfo.td - ARM Register defs ----------*- tablegen -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file contains declarations that describe the AArch64 register file
11//
12//===----------------------------------------------------------------------===//
13
14let Namespace = "AArch64" in {
15def sub_128 : SubRegIndex<128>;
16def sub_64 : SubRegIndex<64>;
17def sub_32 : SubRegIndex<32>;
18def sub_16 : SubRegIndex<16>;
19def sub_8  : SubRegIndex<8>;
20
21// Note: Code depends on these having consecutive numbers.
22def qqsub : SubRegIndex<256, 256>;
23
24def qsub_0 : SubRegIndex<128>;
25def qsub_1 : SubRegIndex<128, 128>;
26def qsub_2 : ComposedSubRegIndex<qqsub, qsub_0>;
27def qsub_3 : ComposedSubRegIndex<qqsub, qsub_1>;
28
29def dsub_0 : SubRegIndex<64>;
30def dsub_1 : SubRegIndex<64, 64>;
31def dsub_2 : ComposedSubRegIndex<qsub_1, dsub_0>;
32def dsub_3 : ComposedSubRegIndex<qsub_1, dsub_1>;
33def dsub_4 : ComposedSubRegIndex<qsub_2, dsub_0>;
34}
35
36// Registers are identified with 5-bit ID numbers.
37class AArch64Reg<bits<16> enc, string n> : Register<n> {
38  let HWEncoding = enc;
39  let Namespace = "AArch64";
40}
41
42class AArch64RegWithSubs<bits<16> enc, string n, list<Register> subregs = [],
43                         list<SubRegIndex> inds = []>
44      : AArch64Reg<enc, n> {
45  let SubRegs = subregs;
46  let SubRegIndices = inds;
47}
48
49//===----------------------------------------------------------------------===//
50//  Integer registers: w0-w30, wzr, wsp, x0-x30, xzr, sp
51//===----------------------------------------------------------------------===//
52
53foreach Index = 0-30 in {
54  def W#Index : AArch64Reg< Index, "w"#Index>, DwarfRegNum<[Index]>;
55}
56
57def WSP : AArch64Reg<31, "wsp">, DwarfRegNum<[31]>;
58def WZR : AArch64Reg<31, "wzr">;
59
60// Could be combined with previous loop, but this way leaves w and x registers
61// consecutive as LLVM register numbers, which makes for easier debugging.
62foreach Index = 0-30 in {
63  def X#Index : AArch64RegWithSubs<Index, "x"#Index,
64                                   [!cast<Register>("W"#Index)], [sub_32]>,
65                DwarfRegNum<[Index]>;
66}
67
68def XSP : AArch64RegWithSubs<31, "sp", [WSP], [sub_32]>, DwarfRegNum<[31]>;
69def XZR : AArch64RegWithSubs<31, "xzr", [WZR], [sub_32]>;
70
71// Most instructions treat register 31 as zero for reads and a black-hole for
72// writes.
73
74// Note that the order of registers is important for the Disassembler here:
75// tablegen uses it to form MCRegisterClass::getRegister, which we assume can
76// take an encoding value.
77def GPR32 : RegisterClass<"AArch64", [i32], 32,
78                          (add (sequence "W%u", 0, 30), WZR)> {
79}
80
81def GPR64 : RegisterClass<"AArch64", [i64], 64,
82                          (add (sequence "X%u", 0, 30), XZR)> {
83}
84
85def GPR32nowzr : RegisterClass<"AArch64", [i32], 32,
86                               (sequence "W%u", 0, 30)> {
87}
88
89def GPR64noxzr : RegisterClass<"AArch64", [i64], 64,
90                               (sequence "X%u", 0, 30)> {
91}
92
93// For tail calls, we can't use callee-saved registers or the structure-return
94// register, as they are supposed to be live across function calls and may be
95// clobbered by the epilogue.
96def tcGPR64 : RegisterClass<"AArch64", [i64], 64,
97                            (add (sequence "X%u", 0, 7),
98                                 (sequence "X%u", 9, 18))> {
99}
100
101
102// Certain addressing-useful instructions accept sp directly. Again the order of
103// registers is important to the Disassembler.
104def GPR32wsp : RegisterClass<"AArch64", [i32], 32,
105                             (add (sequence "W%u", 0, 30), WSP)> {
106}
107
108def GPR64xsp : RegisterClass<"AArch64", [i64], 64,
109                             (add (sequence "X%u", 0, 30), XSP)> {
110}
111
112// Some aliases *only* apply to SP (e.g. MOV uses different encoding for SP and
113// non-SP variants). We can't use a bare register in those patterns because
114// TableGen doesn't like it, so we need a class containing just stack registers
115def Rxsp : RegisterClass<"AArch64", [i64], 64,
116                         (add XSP)> {
117}
118
119def Rwsp : RegisterClass<"AArch64", [i32], 32,
120                         (add WSP)> {
121}
122
123//===----------------------------------------------------------------------===//
124//  Scalar registers in the vector unit:
125//  b0-b31, h0-h31, s0-s31, d0-d31, q0-q31
126//===----------------------------------------------------------------------===//
127
128foreach Index = 0-31 in {
129  def B # Index : AArch64Reg< Index, "b" # Index>,
130                  DwarfRegNum<[!add(Index, 64)]>;
131
132  def H # Index : AArch64RegWithSubs<Index, "h" # Index,
133                                     [!cast<Register>("B" # Index)], [sub_8]>,
134                  DwarfRegNum<[!add(Index, 64)]>;
135
136  def S # Index : AArch64RegWithSubs<Index, "s" # Index,
137                                     [!cast<Register>("H" # Index)], [sub_16]>,
138                  DwarfRegNum<[!add(Index, 64)]>;
139
140  def D # Index : AArch64RegWithSubs<Index, "d" # Index,
141                                     [!cast<Register>("S" # Index)], [sub_32]>,
142                  DwarfRegNum<[!add(Index, 64)]>;
143
144  def Q # Index : AArch64RegWithSubs<Index, "q" # Index,
145                                     [!cast<Register>("D" # Index)], [sub_64]>,
146                  DwarfRegNum<[!add(Index, 64)]>;
147}
148
149
150def FPR8 : RegisterClass<"AArch64", [i8, v1i8], 8,
151                          (sequence "B%u", 0, 31)> {
152}
153
154def FPR16 : RegisterClass<"AArch64", [f16, v1i16], 16,
155                          (sequence "H%u", 0, 31)> {
156}
157
158def FPR32 : RegisterClass<"AArch64", [f32, v1i32, v1f32], 32,
159                          (sequence "S%u", 0, 31)> {
160}
161
162def FPR64 : RegisterClass<"AArch64",
163                          [f64, v2f32, v2i32, v4i16, v8i8, v1i64, v1f64],
164                          64, (sequence "D%u", 0, 31)>;
165
166def FPR128 : RegisterClass<"AArch64",
167                           [f128, v2f64, v2i64, v4f32, v4i32, v8i16, v16i8],
168                           128, (sequence "Q%u", 0, 31)>;
169
170def FPR64Lo : RegisterClass<"AArch64",
171                            [f64, v2f32, v2i32, v4i16, v8i8, v1i64, v1f64],
172                            64, (sequence "D%u", 0, 15)>;
173
174def FPR128Lo : RegisterClass<"AArch64",
175                             [f128, v2f64, v2i64, v4f32, v4i32, v8i16, v16i8],
176                             128, (sequence "Q%u", 0, 15)>;
177
178//===----------------------------------------------------------------------===//
179//  Vector registers:
180//===----------------------------------------------------------------------===//
181
182def VPR64AsmOperand : AsmOperandClass {
183  let Name = "VPR";
184  let PredicateMethod = "isReg";
185  let RenderMethod = "addRegOperands";
186}
187
188def VPR64 : RegisterOperand<FPR64, "printVPRRegister">;
189
190def VPR128 : RegisterOperand<FPR128, "printVPRRegister">;
191
192def VPR64Lo : RegisterOperand<FPR64Lo, "printVPRRegister">;
193
194def VPR128Lo : RegisterOperand<FPR128Lo, "printVPRRegister">;
195
196// Flags register
197def NZCV : Register<"nzcv"> {
198  let Namespace = "AArch64";
199}
200
201def FlagClass : RegisterClass<"AArch64", [i32], 32, (add NZCV)> {
202  let CopyCost = -1;
203  let isAllocatable = 0;
204}
205
206//===----------------------------------------------------------------------===//
207//  Consecutive vector registers
208//===----------------------------------------------------------------------===//
209// 2 Consecutive 64-bit registers: D0_D1, D1_D2, ..., D30_D31
210def Tuples2D : RegisterTuples<[dsub_0, dsub_1],
211                              [(rotl FPR64, 0), (rotl FPR64, 1)]>;
212                              
213// 3 Consecutive 64-bit registers: D0_D1_D2, ..., D31_D0_D1
214def Tuples3D : RegisterTuples<[dsub_0, dsub_1, dsub_2],
215                              [(rotl FPR64, 0), (rotl FPR64, 1),
216                               (rotl FPR64, 2)]>;
217                               
218// 4 Consecutive 64-bit registers: D0_D1_D2_D3, ..., D31_D0_D1_D2
219def Tuples4D : RegisterTuples<[dsub_0, dsub_1, dsub_2, dsub_3],
220                              [(rotl FPR64, 0), (rotl FPR64, 1),
221                               (rotl FPR64, 2), (rotl FPR64, 3)]>;
222
223// 2 Consecutive 128-bit registers: Q0_Q1, Q1_Q2, ..., Q30_Q31
224def Tuples2Q : RegisterTuples<[qsub_0, qsub_1],
225                              [(rotl FPR128, 0), (rotl FPR128, 1)]>;
226
227// 3 Consecutive 128-bit registers: Q0_Q1_Q2, ..., Q31_Q0_Q1
228def Tuples3Q : RegisterTuples<[qsub_0, qsub_1, qsub_2],
229                              [(rotl FPR128, 0), (rotl FPR128, 1),
230                               (rotl FPR128, 2)]>;
231                               
232// 4 Consecutive 128-bit registers: Q0_Q1_Q2_Q3, ..., Q31_Q0_Q1_Q2
233def Tuples4Q : RegisterTuples<[qsub_0, qsub_1, qsub_2, qsub_3],
234                              [(rotl FPR128, 0), (rotl FPR128, 1),
235                               (rotl FPR128, 2), (rotl FPR128, 3)]>;
236
237// The followings are super register classes to model 2/3/4 consecutive
238// 64-bit/128-bit registers.
239
240def DPair : RegisterClass<"AArch64", [v2i64], 64, (add Tuples2D)>;
241
242def DTriple : RegisterClass<"AArch64", [untyped], 64, (add Tuples3D)> {
243  let Size = 192; // 3 x 64 bits, we have no predefined type of that size.
244}
245
246def DQuad : RegisterClass<"AArch64", [v4i64], 64, (add Tuples4D)>;
247
248def QPair : RegisterClass<"AArch64", [v4i64], 128, (add Tuples2Q)>;
249
250def QTriple : RegisterClass<"AArch64", [untyped], 128, (add Tuples3Q)> {
251  let Size = 384; // 3 x 128 bits, we have no predefined type of that size.
252}
253
254def QQuad : RegisterClass<"AArch64", [v8i64], 128, (add Tuples4Q)>;
255
256
257// The followings are vector list operands
258multiclass VectorList_operands<string PREFIX, string LAYOUT, int Count,
259                               RegisterClass RegList> {
260  def _asmoperand : AsmOperandClass {
261    let Name = PREFIX # LAYOUT # Count;
262    let RenderMethod = "addVectorListOperands";
263    let PredicateMethod = 
264        "isVectorList<A64Layout::_" # LAYOUT # ", " # Count # ">";
265    let ParserMethod = "ParseVectorList";
266  }
267
268  def _operand : RegisterOperand<RegList,
269        "printVectorList<A64Layout::_" # LAYOUT # ", " # Count # ">"> {
270    let ParserMatchClass =
271      !cast<AsmOperandClass>(PREFIX # LAYOUT # "_asmoperand");
272  }
273}
274
275multiclass VectorList_BHSD<string PREFIX, int Count, RegisterClass DRegList,
276                           RegisterClass QRegList> {
277  defm 8B : VectorList_operands<PREFIX, "8B", Count, DRegList>;
278  defm 4H : VectorList_operands<PREFIX, "4H", Count, DRegList>;
279  defm 2S : VectorList_operands<PREFIX, "2S", Count, DRegList>;
280  defm 1D : VectorList_operands<PREFIX, "1D", Count, DRegList>;
281  defm 16B : VectorList_operands<PREFIX, "16B", Count, QRegList>;
282  defm 8H : VectorList_operands<PREFIX, "8H", Count, QRegList>;
283  defm 4S : VectorList_operands<PREFIX, "4S", Count, QRegList>;
284  defm 2D : VectorList_operands<PREFIX, "2D", Count, QRegList>;
285}
286
287// Vector list operand with 1/2/3/4 registers: VOne8B_operand,..., VQuad2D_operand
288defm VOne : VectorList_BHSD<"VOne", 1, FPR64, FPR128>;
289defm VPair : VectorList_BHSD<"VPair", 2, DPair, QPair>;
290defm VTriple : VectorList_BHSD<"VTriple", 3, DTriple, QTriple>;
291defm VQuad : VectorList_BHSD<"VQuad", 4, DQuad, QQuad>;