]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===// |
970d7e83 LB |
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 | //===----------------------------------------------------------------------===// | |
970d7e83 | 9 | |
970d7e83 | 10 | //===----------------------------------------------------------------------===// |
1a4d82fc JJ |
11 | // Describe AArch64 instructions format here |
12 | // | |
13 | ||
14 | // Format specifies the encoding used by the instruction. This is part of the | |
15 | // ad-hoc solution used to emit machine instruction encodings by our machine | |
16 | // code emitter. | |
17 | class Format<bits<2> val> { | |
18 | bits<2> Value = val; | |
19 | } | |
970d7e83 | 20 | |
1a4d82fc JJ |
21 | def PseudoFrm : Format<0>; |
22 | def NormalFrm : Format<1>; // Do we need any others? | |
970d7e83 | 23 | |
1a4d82fc JJ |
24 | // AArch64 Instruction Format |
25 | class AArch64Inst<Format f, string cstr> : Instruction { | |
26 | field bits<32> Inst; // Instruction encoding. | |
27 | // Mask of bits that cause an encoding to be UNPREDICTABLE. | |
28 | // If a bit is set, then if the corresponding bit in the | |
29 | // target encoding differs from its value in the "Inst" field, | |
30 | // the instruction is UNPREDICTABLE (SoftFail in abstract parlance). | |
970d7e83 LB |
31 | field bits<32> Unpredictable = 0; |
32 | // SoftFail is the generic name for this field, but we alias it so | |
33 | // as to make it more obvious what it means in ARM-land. | |
34 | field bits<32> SoftFail = Unpredictable; | |
1a4d82fc JJ |
35 | let Namespace = "AArch64"; |
36 | Format F = f; | |
37 | bits<2> Form = F.Value; | |
38 | let Pattern = []; | |
39 | let Constraints = cstr; | |
40 | } | |
41 | ||
42 | // Pseudo instructions (don't have encoding information) | |
43 | class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = ""> | |
44 | : AArch64Inst<PseudoFrm, cstr> { | |
45 | dag OutOperandList = oops; | |
46 | dag InOperandList = iops; | |
47 | let Pattern = pattern; | |
48 | let isCodeGenOnly = 1; | |
49 | } | |
970d7e83 | 50 | |
1a4d82fc JJ |
51 | // Real instructions (have encoding information) |
52 | class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> { | |
53 | let Pattern = pattern; | |
970d7e83 | 54 | let Size = 4; |
1a4d82fc | 55 | } |
970d7e83 | 56 | |
1a4d82fc JJ |
57 | // Normal instructions |
58 | class I<dag oops, dag iops, string asm, string operands, string cstr, | |
59 | list<dag> pattern> | |
60 | : EncodedI<cstr, pattern> { | |
61 | dag OutOperandList = oops; | |
62 | dag InOperandList = iops; | |
63 | let AsmString = !strconcat(asm, operands); | |
970d7e83 LB |
64 | } |
65 | ||
1a4d82fc JJ |
66 | class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>; |
67 | class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>; | |
68 | class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>; | |
69 | ||
70 | // Helper fragment for an extract of the high portion of a 128-bit vector. | |
71 | def extract_high_v16i8 : | |
72 | UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>; | |
73 | def extract_high_v8i16 : | |
74 | UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>; | |
75 | def extract_high_v4i32 : | |
76 | UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>; | |
77 | def extract_high_v2i64 : | |
78 | UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>; | |
79 | ||
80 | //===----------------------------------------------------------------------===// | |
81 | // Asm Operand Classes. | |
82 | // | |
970d7e83 | 83 | |
1a4d82fc JJ |
84 | // Shifter operand for arithmetic shifted encodings. |
85 | def ShifterOperand : AsmOperandClass { | |
86 | let Name = "Shifter"; | |
970d7e83 LB |
87 | } |
88 | ||
1a4d82fc JJ |
89 | // Shifter operand for mov immediate encodings. |
90 | def MovImm32ShifterOperand : AsmOperandClass { | |
91 | let SuperClasses = [ShifterOperand]; | |
92 | let Name = "MovImm32Shifter"; | |
93 | let RenderMethod = "addShifterOperands"; | |
94 | let DiagnosticType = "InvalidMovImm32Shift"; | |
95 | } | |
96 | def MovImm64ShifterOperand : AsmOperandClass { | |
97 | let SuperClasses = [ShifterOperand]; | |
98 | let Name = "MovImm64Shifter"; | |
99 | let RenderMethod = "addShifterOperands"; | |
100 | let DiagnosticType = "InvalidMovImm64Shift"; | |
970d7e83 LB |
101 | } |
102 | ||
1a4d82fc JJ |
103 | // Shifter operand for arithmetic register shifted encodings. |
104 | class ArithmeticShifterOperand<int width> : AsmOperandClass { | |
105 | let SuperClasses = [ShifterOperand]; | |
106 | let Name = "ArithmeticShifter" # width; | |
107 | let PredicateMethod = "isArithmeticShifter<" # width # ">"; | |
108 | let RenderMethod = "addShifterOperands"; | |
109 | let DiagnosticType = "AddSubRegShift" # width; | |
110 | } | |
970d7e83 | 111 | |
1a4d82fc JJ |
112 | def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>; |
113 | def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>; | |
970d7e83 | 114 | |
1a4d82fc JJ |
115 | // Shifter operand for logical register shifted encodings. |
116 | class LogicalShifterOperand<int width> : AsmOperandClass { | |
117 | let SuperClasses = [ShifterOperand]; | |
118 | let Name = "LogicalShifter" # width; | |
119 | let PredicateMethod = "isLogicalShifter<" # width # ">"; | |
120 | let RenderMethod = "addShifterOperands"; | |
121 | let DiagnosticType = "AddSubRegShift" # width; | |
122 | } | |
970d7e83 | 123 | |
1a4d82fc JJ |
124 | def LogicalShifterOperand32 : LogicalShifterOperand<32>; |
125 | def LogicalShifterOperand64 : LogicalShifterOperand<64>; | |
970d7e83 | 126 | |
1a4d82fc JJ |
127 | // Shifter operand for logical vector 128/64-bit shifted encodings. |
128 | def LogicalVecShifterOperand : AsmOperandClass { | |
129 | let SuperClasses = [ShifterOperand]; | |
130 | let Name = "LogicalVecShifter"; | |
131 | let RenderMethod = "addShifterOperands"; | |
132 | } | |
133 | def LogicalVecHalfWordShifterOperand : AsmOperandClass { | |
134 | let SuperClasses = [LogicalVecShifterOperand]; | |
135 | let Name = "LogicalVecHalfWordShifter"; | |
136 | let RenderMethod = "addShifterOperands"; | |
970d7e83 LB |
137 | } |
138 | ||
1a4d82fc JJ |
139 | // The "MSL" shifter on the vector MOVI instruction. |
140 | def MoveVecShifterOperand : AsmOperandClass { | |
141 | let SuperClasses = [ShifterOperand]; | |
142 | let Name = "MoveVecShifter"; | |
143 | let RenderMethod = "addShifterOperands"; | |
144 | } | |
970d7e83 | 145 | |
1a4d82fc JJ |
146 | // Extend operand for arithmetic encodings. |
147 | def ExtendOperand : AsmOperandClass { | |
148 | let Name = "Extend"; | |
149 | let DiagnosticType = "AddSubRegExtendLarge"; | |
150 | } | |
151 | def ExtendOperand64 : AsmOperandClass { | |
152 | let SuperClasses = [ExtendOperand]; | |
153 | let Name = "Extend64"; | |
154 | let DiagnosticType = "AddSubRegExtendSmall"; | |
155 | } | |
156 | // 'extend' that's a lsl of a 64-bit register. | |
157 | def ExtendOperandLSL64 : AsmOperandClass { | |
158 | let SuperClasses = [ExtendOperand]; | |
159 | let Name = "ExtendLSL64"; | |
160 | let RenderMethod = "addExtend64Operands"; | |
161 | let DiagnosticType = "AddSubRegExtendLarge"; | |
970d7e83 LB |
162 | } |
163 | ||
1a4d82fc JJ |
164 | // 8-bit floating-point immediate encodings. |
165 | def FPImmOperand : AsmOperandClass { | |
166 | let Name = "FPImm"; | |
167 | let ParserMethod = "tryParseFPImm"; | |
168 | let DiagnosticType = "InvalidFPImm"; | |
169 | } | |
970d7e83 | 170 | |
1a4d82fc JJ |
171 | def CondCode : AsmOperandClass { |
172 | let Name = "CondCode"; | |
173 | let DiagnosticType = "InvalidCondCode"; | |
174 | } | |
970d7e83 | 175 | |
1a4d82fc JJ |
176 | // A 32-bit register pasrsed as 64-bit |
177 | def GPR32as64Operand : AsmOperandClass { | |
178 | let Name = "GPR32as64"; | |
179 | } | |
180 | def GPR32as64 : RegisterOperand<GPR32> { | |
181 | let ParserMatchClass = GPR32as64Operand; | |
970d7e83 LB |
182 | } |
183 | ||
1a4d82fc JJ |
184 | // 8-bit immediate for AdvSIMD where 64-bit values of the form: |
185 | // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh | |
186 | // are encoded as the eight bit value 'abcdefgh'. | |
187 | def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; } | |
970d7e83 | 188 | |
970d7e83 | 189 | |
1a4d82fc JJ |
190 | //===----------------------------------------------------------------------===// |
191 | // Operand Definitions. | |
192 | // | |
970d7e83 | 193 | |
1a4d82fc JJ |
194 | // ADR[P] instruction labels. |
195 | def AdrpOperand : AsmOperandClass { | |
196 | let Name = "AdrpLabel"; | |
197 | let ParserMethod = "tryParseAdrpLabel"; | |
198 | let DiagnosticType = "InvalidLabel"; | |
199 | } | |
200 | def adrplabel : Operand<i64> { | |
201 | let EncoderMethod = "getAdrLabelOpValue"; | |
202 | let PrintMethod = "printAdrpLabel"; | |
203 | let ParserMatchClass = AdrpOperand; | |
970d7e83 LB |
204 | } |
205 | ||
1a4d82fc JJ |
206 | def AdrOperand : AsmOperandClass { |
207 | let Name = "AdrLabel"; | |
208 | let ParserMethod = "tryParseAdrLabel"; | |
209 | let DiagnosticType = "InvalidLabel"; | |
210 | } | |
211 | def adrlabel : Operand<i64> { | |
212 | let EncoderMethod = "getAdrLabelOpValue"; | |
213 | let ParserMatchClass = AdrOperand; | |
214 | } | |
970d7e83 | 215 | |
1a4d82fc JJ |
216 | // simm9 predicate - True if the immediate is in the range [-256, 255]. |
217 | def SImm9Operand : AsmOperandClass { | |
218 | let Name = "SImm9"; | |
219 | let DiagnosticType = "InvalidMemoryIndexedSImm9"; | |
220 | } | |
221 | def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> { | |
222 | let ParserMatchClass = SImm9Operand; | |
970d7e83 LB |
223 | } |
224 | ||
1a4d82fc JJ |
225 | // simm7sN predicate - True if the immediate is a multiple of N in the range |
226 | // [-64 * N, 63 * N]. | |
227 | class SImm7Scaled<int Scale> : AsmOperandClass { | |
228 | let Name = "SImm7s" # Scale; | |
229 | let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7"; | |
230 | } | |
970d7e83 | 231 | |
1a4d82fc JJ |
232 | def SImm7s4Operand : SImm7Scaled<4>; |
233 | def SImm7s8Operand : SImm7Scaled<8>; | |
234 | def SImm7s16Operand : SImm7Scaled<16>; | |
970d7e83 | 235 | |
1a4d82fc JJ |
236 | def simm7s4 : Operand<i32> { |
237 | let ParserMatchClass = SImm7s4Operand; | |
238 | let PrintMethod = "printImmScale<4>"; | |
239 | } | |
970d7e83 | 240 | |
1a4d82fc JJ |
241 | def simm7s8 : Operand<i32> { |
242 | let ParserMatchClass = SImm7s8Operand; | |
243 | let PrintMethod = "printImmScale<8>"; | |
970d7e83 LB |
244 | } |
245 | ||
1a4d82fc JJ |
246 | def simm7s16 : Operand<i32> { |
247 | let ParserMatchClass = SImm7s16Operand; | |
248 | let PrintMethod = "printImmScale<16>"; | |
249 | } | |
970d7e83 | 250 | |
1a4d82fc JJ |
251 | class AsmImmRange<int Low, int High> : AsmOperandClass { |
252 | let Name = "Imm" # Low # "_" # High; | |
253 | let DiagnosticType = "InvalidImm" # Low # "_" # High; | |
970d7e83 LB |
254 | } |
255 | ||
1a4d82fc JJ |
256 | def Imm1_8Operand : AsmImmRange<1, 8>; |
257 | def Imm1_16Operand : AsmImmRange<1, 16>; | |
258 | def Imm1_32Operand : AsmImmRange<1, 32>; | |
259 | def Imm1_64Operand : AsmImmRange<1, 64>; | |
970d7e83 | 260 | |
1a4d82fc JJ |
261 | def MovZSymbolG3AsmOperand : AsmOperandClass { |
262 | let Name = "MovZSymbolG3"; | |
263 | let RenderMethod = "addImmOperands"; | |
970d7e83 LB |
264 | } |
265 | ||
1a4d82fc JJ |
266 | def movz_symbol_g3 : Operand<i32> { |
267 | let ParserMatchClass = MovZSymbolG3AsmOperand; | |
268 | } | |
970d7e83 | 269 | |
1a4d82fc JJ |
270 | def MovZSymbolG2AsmOperand : AsmOperandClass { |
271 | let Name = "MovZSymbolG2"; | |
272 | let RenderMethod = "addImmOperands"; | |
970d7e83 LB |
273 | } |
274 | ||
1a4d82fc JJ |
275 | def movz_symbol_g2 : Operand<i32> { |
276 | let ParserMatchClass = MovZSymbolG2AsmOperand; | |
277 | } | |
970d7e83 | 278 | |
1a4d82fc JJ |
279 | def MovZSymbolG1AsmOperand : AsmOperandClass { |
280 | let Name = "MovZSymbolG1"; | |
281 | let RenderMethod = "addImmOperands"; | |
282 | } | |
970d7e83 | 283 | |
1a4d82fc JJ |
284 | def movz_symbol_g1 : Operand<i32> { |
285 | let ParserMatchClass = MovZSymbolG1AsmOperand; | |
970d7e83 LB |
286 | } |
287 | ||
1a4d82fc JJ |
288 | def MovZSymbolG0AsmOperand : AsmOperandClass { |
289 | let Name = "MovZSymbolG0"; | |
290 | let RenderMethod = "addImmOperands"; | |
291 | } | |
970d7e83 | 292 | |
1a4d82fc JJ |
293 | def movz_symbol_g0 : Operand<i32> { |
294 | let ParserMatchClass = MovZSymbolG0AsmOperand; | |
970d7e83 LB |
295 | } |
296 | ||
1a4d82fc JJ |
297 | def MovKSymbolG3AsmOperand : AsmOperandClass { |
298 | let Name = "MovKSymbolG3"; | |
299 | let RenderMethod = "addImmOperands"; | |
970d7e83 LB |
300 | } |
301 | ||
1a4d82fc JJ |
302 | def movk_symbol_g3 : Operand<i32> { |
303 | let ParserMatchClass = MovKSymbolG3AsmOperand; | |
304 | } | |
970d7e83 | 305 | |
1a4d82fc JJ |
306 | def MovKSymbolG2AsmOperand : AsmOperandClass { |
307 | let Name = "MovKSymbolG2"; | |
308 | let RenderMethod = "addImmOperands"; | |
309 | } | |
970d7e83 | 310 | |
1a4d82fc JJ |
311 | def movk_symbol_g2 : Operand<i32> { |
312 | let ParserMatchClass = MovKSymbolG2AsmOperand; | |
970d7e83 LB |
313 | } |
314 | ||
1a4d82fc JJ |
315 | def MovKSymbolG1AsmOperand : AsmOperandClass { |
316 | let Name = "MovKSymbolG1"; | |
317 | let RenderMethod = "addImmOperands"; | |
318 | } | |
970d7e83 | 319 | |
1a4d82fc JJ |
320 | def movk_symbol_g1 : Operand<i32> { |
321 | let ParserMatchClass = MovKSymbolG1AsmOperand; | |
970d7e83 LB |
322 | } |
323 | ||
1a4d82fc JJ |
324 | def MovKSymbolG0AsmOperand : AsmOperandClass { |
325 | let Name = "MovKSymbolG0"; | |
326 | let RenderMethod = "addImmOperands"; | |
327 | } | |
970d7e83 | 328 | |
1a4d82fc JJ |
329 | def movk_symbol_g0 : Operand<i32> { |
330 | let ParserMatchClass = MovKSymbolG0AsmOperand; | |
970d7e83 LB |
331 | } |
332 | ||
1a4d82fc JJ |
333 | class fixedpoint_i32<ValueType FloatVT> |
334 | : Operand<FloatVT>, | |
335 | ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> { | |
336 | let EncoderMethod = "getFixedPointScaleOpValue"; | |
337 | let DecoderMethod = "DecodeFixedPointScaleImm32"; | |
338 | let ParserMatchClass = Imm1_32Operand; | |
339 | } | |
970d7e83 | 340 | |
1a4d82fc JJ |
341 | class fixedpoint_i64<ValueType FloatVT> |
342 | : Operand<FloatVT>, | |
343 | ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> { | |
344 | let EncoderMethod = "getFixedPointScaleOpValue"; | |
345 | let DecoderMethod = "DecodeFixedPointScaleImm64"; | |
346 | let ParserMatchClass = Imm1_64Operand; | |
970d7e83 LB |
347 | } |
348 | ||
1a4d82fc JJ |
349 | def fixedpoint_f32_i32 : fixedpoint_i32<f32>; |
350 | def fixedpoint_f64_i32 : fixedpoint_i32<f64>; | |
970d7e83 | 351 | |
1a4d82fc JJ |
352 | def fixedpoint_f32_i64 : fixedpoint_i64<f32>; |
353 | def fixedpoint_f64_i64 : fixedpoint_i64<f64>; | |
354 | ||
355 | def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{ | |
356 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9); | |
357 | }]> { | |
358 | let EncoderMethod = "getVecShiftR8OpValue"; | |
359 | let DecoderMethod = "DecodeVecShiftR8Imm"; | |
360 | let ParserMatchClass = Imm1_8Operand; | |
361 | } | |
362 | def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{ | |
363 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17); | |
364 | }]> { | |
365 | let EncoderMethod = "getVecShiftR16OpValue"; | |
366 | let DecoderMethod = "DecodeVecShiftR16Imm"; | |
367 | let ParserMatchClass = Imm1_16Operand; | |
368 | } | |
369 | def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{ | |
370 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9); | |
371 | }]> { | |
372 | let EncoderMethod = "getVecShiftR16OpValue"; | |
373 | let DecoderMethod = "DecodeVecShiftR16ImmNarrow"; | |
374 | let ParserMatchClass = Imm1_8Operand; | |
375 | } | |
376 | def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{ | |
377 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33); | |
378 | }]> { | |
379 | let EncoderMethod = "getVecShiftR32OpValue"; | |
380 | let DecoderMethod = "DecodeVecShiftR32Imm"; | |
381 | let ParserMatchClass = Imm1_32Operand; | |
382 | } | |
383 | def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{ | |
384 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17); | |
385 | }]> { | |
386 | let EncoderMethod = "getVecShiftR32OpValue"; | |
387 | let DecoderMethod = "DecodeVecShiftR32ImmNarrow"; | |
388 | let ParserMatchClass = Imm1_16Operand; | |
389 | } | |
390 | def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{ | |
391 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65); | |
392 | }]> { | |
393 | let EncoderMethod = "getVecShiftR64OpValue"; | |
394 | let DecoderMethod = "DecodeVecShiftR64Imm"; | |
395 | let ParserMatchClass = Imm1_64Operand; | |
396 | } | |
397 | def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{ | |
398 | return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33); | |
399 | }]> { | |
400 | let EncoderMethod = "getVecShiftR64OpValue"; | |
401 | let DecoderMethod = "DecodeVecShiftR64ImmNarrow"; | |
402 | let ParserMatchClass = Imm1_32Operand; | |
970d7e83 LB |
403 | } |
404 | ||
1a4d82fc JJ |
405 | def Imm0_7Operand : AsmImmRange<0, 7>; |
406 | def Imm0_15Operand : AsmImmRange<0, 15>; | |
407 | def Imm0_31Operand : AsmImmRange<0, 31>; | |
408 | def Imm0_63Operand : AsmImmRange<0, 63>; | |
970d7e83 | 409 | |
1a4d82fc JJ |
410 | def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{ |
411 | return (((uint32_t)Imm) < 8); | |
412 | }]> { | |
413 | let EncoderMethod = "getVecShiftL8OpValue"; | |
414 | let DecoderMethod = "DecodeVecShiftL8Imm"; | |
415 | let ParserMatchClass = Imm0_7Operand; | |
416 | } | |
417 | def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{ | |
418 | return (((uint32_t)Imm) < 16); | |
419 | }]> { | |
420 | let EncoderMethod = "getVecShiftL16OpValue"; | |
421 | let DecoderMethod = "DecodeVecShiftL16Imm"; | |
422 | let ParserMatchClass = Imm0_15Operand; | |
423 | } | |
424 | def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{ | |
425 | return (((uint32_t)Imm) < 32); | |
426 | }]> { | |
427 | let EncoderMethod = "getVecShiftL32OpValue"; | |
428 | let DecoderMethod = "DecodeVecShiftL32Imm"; | |
429 | let ParserMatchClass = Imm0_31Operand; | |
430 | } | |
431 | def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{ | |
432 | return (((uint32_t)Imm) < 64); | |
433 | }]> { | |
434 | let EncoderMethod = "getVecShiftL64OpValue"; | |
435 | let DecoderMethod = "DecodeVecShiftL64Imm"; | |
436 | let ParserMatchClass = Imm0_63Operand; | |
970d7e83 LB |
437 | } |
438 | ||
439 | ||
1a4d82fc JJ |
440 | // Crazy immediate formats used by 32-bit and 64-bit logical immediate |
441 | // instructions for splatting repeating bit patterns across the immediate. | |
442 | def logical_imm32_XFORM : SDNodeXForm<imm, [{ | |
443 | uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32); | |
444 | return CurDAG->getTargetConstant(enc, MVT::i32); | |
445 | }]>; | |
446 | def logical_imm64_XFORM : SDNodeXForm<imm, [{ | |
447 | uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64); | |
448 | return CurDAG->getTargetConstant(enc, MVT::i32); | |
449 | }]>; | |
450 | ||
451 | let DiagnosticType = "LogicalSecondSource" in { | |
452 | def LogicalImm32Operand : AsmOperandClass { | |
453 | let Name = "LogicalImm32"; | |
454 | } | |
455 | def LogicalImm64Operand : AsmOperandClass { | |
456 | let Name = "LogicalImm64"; | |
457 | } | |
458 | def LogicalImm32NotOperand : AsmOperandClass { | |
459 | let Name = "LogicalImm32Not"; | |
460 | } | |
461 | def LogicalImm64NotOperand : AsmOperandClass { | |
462 | let Name = "LogicalImm64Not"; | |
463 | } | |
464 | } | |
465 | def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{ | |
466 | return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32); | |
467 | }], logical_imm32_XFORM> { | |
468 | let PrintMethod = "printLogicalImm32"; | |
469 | let ParserMatchClass = LogicalImm32Operand; | |
470 | } | |
471 | def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{ | |
472 | return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64); | |
473 | }], logical_imm64_XFORM> { | |
474 | let PrintMethod = "printLogicalImm64"; | |
475 | let ParserMatchClass = LogicalImm64Operand; | |
476 | } | |
477 | def logical_imm32_not : Operand<i32> { | |
478 | let ParserMatchClass = LogicalImm32NotOperand; | |
479 | } | |
480 | def logical_imm64_not : Operand<i64> { | |
481 | let ParserMatchClass = LogicalImm64NotOperand; | |
970d7e83 LB |
482 | } |
483 | ||
1a4d82fc JJ |
484 | // imm0_65535 predicate - True if the immediate is in the range [0,65535]. |
485 | def Imm0_65535Operand : AsmImmRange<0, 65535>; | |
486 | def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{ | |
487 | return ((uint32_t)Imm) < 65536; | |
488 | }]> { | |
489 | let ParserMatchClass = Imm0_65535Operand; | |
490 | let PrintMethod = "printHexImm"; | |
491 | } | |
970d7e83 | 492 | |
1a4d82fc JJ |
493 | // imm0_255 predicate - True if the immediate is in the range [0,255]. |
494 | def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; } | |
495 | def imm0_255 : Operand<i32>, ImmLeaf<i32, [{ | |
496 | return ((uint32_t)Imm) < 256; | |
497 | }]> { | |
498 | let ParserMatchClass = Imm0_255Operand; | |
499 | let PrintMethod = "printHexImm"; | |
970d7e83 LB |
500 | } |
501 | ||
1a4d82fc JJ |
502 | // imm0_127 predicate - True if the immediate is in the range [0,127] |
503 | def Imm0_127Operand : AsmImmRange<0, 127>; | |
504 | def imm0_127 : Operand<i32>, ImmLeaf<i32, [{ | |
505 | return ((uint32_t)Imm) < 128; | |
506 | }]> { | |
507 | let ParserMatchClass = Imm0_127Operand; | |
508 | let PrintMethod = "printHexImm"; | |
509 | } | |
970d7e83 | 510 | |
1a4d82fc JJ |
511 | // NOTE: These imm0_N operands have to be of type i64 because i64 is the size |
512 | // for all shift-amounts. | |
513 | ||
514 | // imm0_63 predicate - True if the immediate is in the range [0,63] | |
515 | def imm0_63 : Operand<i64>, ImmLeaf<i64, [{ | |
516 | return ((uint64_t)Imm) < 64; | |
517 | }]> { | |
518 | let ParserMatchClass = Imm0_63Operand; | |
970d7e83 LB |
519 | } |
520 | ||
1a4d82fc JJ |
521 | // imm0_31 predicate - True if the immediate is in the range [0,31] |
522 | def imm0_31 : Operand<i64>, ImmLeaf<i64, [{ | |
523 | return ((uint64_t)Imm) < 32; | |
524 | }]> { | |
525 | let ParserMatchClass = Imm0_31Operand; | |
970d7e83 LB |
526 | } |
527 | ||
1a4d82fc JJ |
528 | // imm0_15 predicate - True if the immediate is in the range [0,15] |
529 | def imm0_15 : Operand<i64>, ImmLeaf<i64, [{ | |
530 | return ((uint64_t)Imm) < 16; | |
531 | }]> { | |
532 | let ParserMatchClass = Imm0_15Operand; | |
533 | } | |
970d7e83 | 534 | |
1a4d82fc JJ |
535 | // imm0_7 predicate - True if the immediate is in the range [0,7] |
536 | def imm0_7 : Operand<i64>, ImmLeaf<i64, [{ | |
537 | return ((uint64_t)Imm) < 8; | |
538 | }]> { | |
539 | let ParserMatchClass = Imm0_7Operand; | |
540 | } | |
970d7e83 | 541 | |
1a4d82fc JJ |
542 | // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15] |
543 | def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{ | |
544 | return ((uint32_t)Imm) < 16; | |
545 | }]>; | |
546 | ||
547 | // An arithmetic shifter operand: | |
548 | // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr | |
549 | // {5-0} - imm6 | |
550 | class arith_shift<ValueType Ty, int width> : Operand<Ty> { | |
551 | let PrintMethod = "printShifter"; | |
552 | let ParserMatchClass = !cast<AsmOperandClass>( | |
553 | "ArithmeticShifterOperand" # width); | |
970d7e83 LB |
554 | } |
555 | ||
1a4d82fc JJ |
556 | def arith_shift32 : arith_shift<i32, 32>; |
557 | def arith_shift64 : arith_shift<i64, 64>; | |
970d7e83 | 558 | |
1a4d82fc JJ |
559 | class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width> |
560 | : Operand<Ty>, | |
561 | ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> { | |
562 | let PrintMethod = "printShiftedRegister"; | |
563 | let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width)); | |
970d7e83 LB |
564 | } |
565 | ||
1a4d82fc JJ |
566 | def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>; |
567 | def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>; | |
568 | ||
569 | // An arithmetic shifter operand: | |
570 | // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror | |
571 | // {5-0} - imm6 | |
572 | class logical_shift<int width> : Operand<i32> { | |
573 | let PrintMethod = "printShifter"; | |
574 | let ParserMatchClass = !cast<AsmOperandClass>( | |
575 | "LogicalShifterOperand" # width); | |
970d7e83 LB |
576 | } |
577 | ||
1a4d82fc JJ |
578 | def logical_shift32 : logical_shift<32>; |
579 | def logical_shift64 : logical_shift<64>; | |
580 | ||
581 | class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop> | |
582 | : Operand<Ty>, | |
583 | ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> { | |
584 | let PrintMethod = "printShiftedRegister"; | |
585 | let MIOperandInfo = (ops regclass, shiftop); | |
970d7e83 LB |
586 | } |
587 | ||
1a4d82fc JJ |
588 | def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>; |
589 | def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>; | |
590 | ||
591 | // A logical vector shifter operand: | |
592 | // {7-6} - shift type: 00 = lsl | |
593 | // {5-0} - imm6: #0, #8, #16, or #24 | |
594 | def logical_vec_shift : Operand<i32> { | |
595 | let PrintMethod = "printShifter"; | |
596 | let EncoderMethod = "getVecShifterOpValue"; | |
597 | let ParserMatchClass = LogicalVecShifterOperand; | |
970d7e83 LB |
598 | } |
599 | ||
1a4d82fc JJ |
600 | // A logical vector half-word shifter operand: |
601 | // {7-6} - shift type: 00 = lsl | |
602 | // {5-0} - imm6: #0 or #8 | |
603 | def logical_vec_hw_shift : Operand<i32> { | |
604 | let PrintMethod = "printShifter"; | |
605 | let EncoderMethod = "getVecShifterOpValue"; | |
606 | let ParserMatchClass = LogicalVecHalfWordShifterOperand; | |
970d7e83 LB |
607 | } |
608 | ||
1a4d82fc JJ |
609 | // A vector move shifter operand: |
610 | // {0} - imm1: #8 or #16 | |
611 | def move_vec_shift : Operand<i32> { | |
612 | let PrintMethod = "printShifter"; | |
613 | let EncoderMethod = "getMoveVecShifterOpValue"; | |
614 | let ParserMatchClass = MoveVecShifterOperand; | |
615 | } | |
970d7e83 | 616 | |
1a4d82fc JJ |
617 | def AddSubImmOperand : AsmOperandClass { |
618 | let Name = "AddSubImm"; | |
619 | let ParserMethod = "tryParseAddSubImm"; | |
620 | let DiagnosticType = "AddSubSecondSource"; | |
621 | } | |
622 | // An ADD/SUB immediate shifter operand: | |
623 | // second operand: | |
624 | // {7-6} - shift type: 00 = lsl | |
625 | // {5-0} - imm6: #0 or #12 | |
626 | class addsub_shifted_imm<ValueType Ty> | |
627 | : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> { | |
628 | let PrintMethod = "printAddSubImm"; | |
629 | let EncoderMethod = "getAddSubImmOpValue"; | |
630 | let ParserMatchClass = AddSubImmOperand; | |
631 | let MIOperandInfo = (ops i32imm, i32imm); | |
970d7e83 LB |
632 | } |
633 | ||
1a4d82fc JJ |
634 | def addsub_shifted_imm32 : addsub_shifted_imm<i32>; |
635 | def addsub_shifted_imm64 : addsub_shifted_imm<i64>; | |
970d7e83 | 636 | |
1a4d82fc JJ |
637 | class neg_addsub_shifted_imm<ValueType Ty> |
638 | : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> { | |
639 | let PrintMethod = "printAddSubImm"; | |
640 | let EncoderMethod = "getAddSubImmOpValue"; | |
641 | let ParserMatchClass = AddSubImmOperand; | |
642 | let MIOperandInfo = (ops i32imm, i32imm); | |
643 | } | |
970d7e83 | 644 | |
1a4d82fc JJ |
645 | def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>; |
646 | def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>; | |
647 | ||
648 | // An extend operand: | |
649 | // {5-3} - extend type | |
650 | // {2-0} - imm3 | |
651 | def arith_extend : Operand<i32> { | |
652 | let PrintMethod = "printArithExtend"; | |
653 | let ParserMatchClass = ExtendOperand; | |
654 | } | |
655 | def arith_extend64 : Operand<i32> { | |
656 | let PrintMethod = "printArithExtend"; | |
657 | let ParserMatchClass = ExtendOperand64; | |
970d7e83 LB |
658 | } |
659 | ||
1a4d82fc JJ |
660 | // 'extend' that's a lsl of a 64-bit register. |
661 | def arith_extendlsl64 : Operand<i32> { | |
662 | let PrintMethod = "printArithExtend"; | |
663 | let ParserMatchClass = ExtendOperandLSL64; | |
664 | } | |
970d7e83 | 665 | |
1a4d82fc JJ |
666 | class arith_extended_reg32<ValueType Ty> : Operand<Ty>, |
667 | ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> { | |
668 | let PrintMethod = "printExtendedRegister"; | |
669 | let MIOperandInfo = (ops GPR32, arith_extend); | |
670 | } | |
970d7e83 | 671 | |
1a4d82fc JJ |
672 | class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>, |
673 | ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> { | |
674 | let PrintMethod = "printExtendedRegister"; | |
675 | let MIOperandInfo = (ops GPR32, arith_extend64); | |
970d7e83 LB |
676 | } |
677 | ||
1a4d82fc JJ |
678 | // Floating-point immediate. |
679 | def fpimm32 : Operand<f32>, | |
680 | PatLeaf<(f32 fpimm), [{ | |
681 | return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1; | |
682 | }], SDNodeXForm<fpimm, [{ | |
683 | APFloat InVal = N->getValueAPF(); | |
684 | uint32_t enc = AArch64_AM::getFP32Imm(InVal); | |
685 | return CurDAG->getTargetConstant(enc, MVT::i32); | |
686 | }]>> { | |
687 | let ParserMatchClass = FPImmOperand; | |
688 | let PrintMethod = "printFPImmOperand"; | |
689 | } | |
690 | def fpimm64 : Operand<f64>, | |
691 | PatLeaf<(f64 fpimm), [{ | |
692 | return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1; | |
693 | }], SDNodeXForm<fpimm, [{ | |
694 | APFloat InVal = N->getValueAPF(); | |
695 | uint32_t enc = AArch64_AM::getFP64Imm(InVal); | |
696 | return CurDAG->getTargetConstant(enc, MVT::i32); | |
697 | }]>> { | |
698 | let ParserMatchClass = FPImmOperand; | |
699 | let PrintMethod = "printFPImmOperand"; | |
700 | } | |
970d7e83 | 701 | |
1a4d82fc JJ |
702 | def fpimm8 : Operand<i32> { |
703 | let ParserMatchClass = FPImmOperand; | |
704 | let PrintMethod = "printFPImmOperand"; | |
970d7e83 LB |
705 | } |
706 | ||
1a4d82fc JJ |
707 | def fpimm0 : PatLeaf<(fpimm), [{ |
708 | return N->isExactlyValue(+0.0); | |
709 | }]>; | |
970d7e83 | 710 | |
1a4d82fc JJ |
711 | // Vector lane operands |
712 | class AsmVectorIndex<string Suffix> : AsmOperandClass { | |
713 | let Name = "VectorIndex" # Suffix; | |
714 | let DiagnosticType = "InvalidIndex" # Suffix; | |
715 | } | |
716 | def VectorIndex1Operand : AsmVectorIndex<"1">; | |
717 | def VectorIndexBOperand : AsmVectorIndex<"B">; | |
718 | def VectorIndexHOperand : AsmVectorIndex<"H">; | |
719 | def VectorIndexSOperand : AsmVectorIndex<"S">; | |
720 | def VectorIndexDOperand : AsmVectorIndex<"D">; | |
970d7e83 | 721 | |
1a4d82fc JJ |
722 | def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{ |
723 | return ((uint64_t)Imm) == 1; | |
724 | }]> { | |
725 | let ParserMatchClass = VectorIndex1Operand; | |
726 | let PrintMethod = "printVectorIndex"; | |
727 | let MIOperandInfo = (ops i64imm); | |
728 | } | |
729 | def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{ | |
730 | return ((uint64_t)Imm) < 16; | |
731 | }]> { | |
732 | let ParserMatchClass = VectorIndexBOperand; | |
733 | let PrintMethod = "printVectorIndex"; | |
734 | let MIOperandInfo = (ops i64imm); | |
735 | } | |
736 | def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{ | |
737 | return ((uint64_t)Imm) < 8; | |
738 | }]> { | |
739 | let ParserMatchClass = VectorIndexHOperand; | |
740 | let PrintMethod = "printVectorIndex"; | |
741 | let MIOperandInfo = (ops i64imm); | |
742 | } | |
743 | def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{ | |
744 | return ((uint64_t)Imm) < 4; | |
745 | }]> { | |
746 | let ParserMatchClass = VectorIndexSOperand; | |
747 | let PrintMethod = "printVectorIndex"; | |
748 | let MIOperandInfo = (ops i64imm); | |
749 | } | |
750 | def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{ | |
751 | return ((uint64_t)Imm) < 2; | |
752 | }]> { | |
753 | let ParserMatchClass = VectorIndexDOperand; | |
754 | let PrintMethod = "printVectorIndex"; | |
755 | let MIOperandInfo = (ops i64imm); | |
970d7e83 LB |
756 | } |
757 | ||
1a4d82fc JJ |
758 | // 8-bit immediate for AdvSIMD where 64-bit values of the form: |
759 | // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh | |
760 | // are encoded as the eight bit value 'abcdefgh'. | |
761 | def simdimmtype10 : Operand<i32>, | |
762 | PatLeaf<(f64 fpimm), [{ | |
763 | return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF() | |
764 | .bitcastToAPInt() | |
765 | .getZExtValue()); | |
766 | }], SDNodeXForm<fpimm, [{ | |
767 | APFloat InVal = N->getValueAPF(); | |
768 | uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF() | |
769 | .bitcastToAPInt() | |
770 | .getZExtValue()); | |
771 | return CurDAG->getTargetConstant(enc, MVT::i32); | |
772 | }]>> { | |
773 | let ParserMatchClass = SIMDImmType10Operand; | |
774 | let PrintMethod = "printSIMDType10Operand"; | |
775 | } | |
970d7e83 | 776 | |
970d7e83 | 777 | |
1a4d82fc JJ |
778 | //--- |
779 | // System management | |
780 | //--- | |
970d7e83 | 781 | |
1a4d82fc JJ |
782 | // Base encoding for system instruction operands. |
783 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in | |
784 | class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands, | |
785 | list<dag> pattern = []> | |
786 | : I<oops, iops, asm, operands, "", pattern> { | |
787 | let Inst{31-22} = 0b1101010100; | |
788 | let Inst{21} = L; | |
970d7e83 LB |
789 | } |
790 | ||
1a4d82fc JJ |
791 | // System instructions which do not have an Rt register. |
792 | class SimpleSystemI<bit L, dag iops, string asm, string operands, | |
793 | list<dag> pattern = []> | |
794 | : BaseSystemI<L, (outs), iops, asm, operands, pattern> { | |
795 | let Inst{4-0} = 0b11111; | |
796 | } | |
970d7e83 | 797 | |
1a4d82fc JJ |
798 | // System instructions which have an Rt register. |
799 | class RtSystemI<bit L, dag oops, dag iops, string asm, string operands> | |
800 | : BaseSystemI<L, oops, iops, asm, operands>, | |
801 | Sched<[WriteSys]> { | |
802 | bits<5> Rt; | |
803 | let Inst{4-0} = Rt; | |
970d7e83 LB |
804 | } |
805 | ||
1a4d82fc JJ |
806 | // Hint instructions that take both a CRm and a 3-bit immediate. |
807 | // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot | |
808 | // model patterns with sufficiently fine granularity | |
809 | let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in | |
810 | class HintI<string mnemonic> | |
811 | : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "", | |
812 | [(int_aarch64_hint imm0_127:$imm)]>, | |
813 | Sched<[WriteHint]> { | |
814 | bits <7> imm; | |
815 | let Inst{20-12} = 0b000110010; | |
816 | let Inst{11-5} = imm; | |
817 | } | |
970d7e83 | 818 | |
1a4d82fc JJ |
819 | // System instructions taking a single literal operand which encodes into |
820 | // CRm. op2 differentiates the opcodes. | |
821 | def BarrierAsmOperand : AsmOperandClass { | |
822 | let Name = "Barrier"; | |
823 | let ParserMethod = "tryParseBarrierOperand"; | |
824 | } | |
825 | def barrier_op : Operand<i32> { | |
826 | let PrintMethod = "printBarrierOption"; | |
827 | let ParserMatchClass = BarrierAsmOperand; | |
828 | } | |
829 | class CRmSystemI<Operand crmtype, bits<3> opc, string asm, | |
830 | list<dag> pattern = []> | |
831 | : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>, | |
832 | Sched<[WriteBarrier]> { | |
833 | bits<4> CRm; | |
834 | let Inst{20-12} = 0b000110011; | |
835 | let Inst{11-8} = CRm; | |
836 | let Inst{7-5} = opc; | |
970d7e83 LB |
837 | } |
838 | ||
1a4d82fc JJ |
839 | // MRS/MSR system instructions. These have different operand classes because |
840 | // a different subset of registers can be accessed through each instruction. | |
841 | def MRSSystemRegisterOperand : AsmOperandClass { | |
842 | let Name = "MRSSystemRegister"; | |
843 | let ParserMethod = "tryParseSysReg"; | |
844 | let DiagnosticType = "MRS"; | |
845 | } | |
846 | // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate. | |
847 | def mrs_sysreg_op : Operand<i32> { | |
848 | let ParserMatchClass = MRSSystemRegisterOperand; | |
849 | let DecoderMethod = "DecodeMRSSystemRegister"; | |
850 | let PrintMethod = "printMRSSystemRegister"; | |
851 | } | |
970d7e83 | 852 | |
1a4d82fc JJ |
853 | def MSRSystemRegisterOperand : AsmOperandClass { |
854 | let Name = "MSRSystemRegister"; | |
855 | let ParserMethod = "tryParseSysReg"; | |
856 | let DiagnosticType = "MSR"; | |
857 | } | |
858 | def msr_sysreg_op : Operand<i32> { | |
859 | let ParserMatchClass = MSRSystemRegisterOperand; | |
860 | let DecoderMethod = "DecodeMSRSystemRegister"; | |
861 | let PrintMethod = "printMSRSystemRegister"; | |
970d7e83 LB |
862 | } |
863 | ||
1a4d82fc JJ |
864 | class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg), |
865 | "mrs", "\t$Rt, $systemreg"> { | |
866 | bits<16> systemreg; | |
867 | let Inst{20-5} = systemreg; | |
868 | } | |
970d7e83 | 869 | |
1a4d82fc JJ |
870 | // FIXME: Some of these def NZCV, others don't. Best way to model that? |
871 | // Explicitly modeling each of the system register as a register class | |
872 | // would do it, but feels like overkill at this point. | |
873 | class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt), | |
874 | "msr", "\t$systemreg, $Rt"> { | |
875 | bits<16> systemreg; | |
876 | let Inst{20-5} = systemreg; | |
877 | } | |
970d7e83 | 878 | |
1a4d82fc JJ |
879 | def SystemPStateFieldOperand : AsmOperandClass { |
880 | let Name = "SystemPStateField"; | |
881 | let ParserMethod = "tryParseSysReg"; | |
882 | } | |
883 | def pstatefield_op : Operand<i32> { | |
884 | let ParserMatchClass = SystemPStateFieldOperand; | |
885 | let PrintMethod = "printSystemPStateField"; | |
970d7e83 LB |
886 | } |
887 | ||
1a4d82fc JJ |
888 | let Defs = [NZCV] in |
889 | class MSRpstateI | |
890 | : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm), | |
891 | "msr", "\t$pstate_field, $imm">, | |
892 | Sched<[WriteSys]> { | |
893 | bits<6> pstatefield; | |
894 | bits<4> imm; | |
895 | let Inst{20-19} = 0b00; | |
896 | let Inst{18-16} = pstatefield{5-3}; | |
897 | let Inst{15-12} = 0b0100; | |
898 | let Inst{11-8} = imm; | |
899 | let Inst{7-5} = pstatefield{2-0}; | |
970d7e83 | 900 | |
1a4d82fc JJ |
901 | let DecoderMethod = "DecodeSystemPStateInstruction"; |
902 | } | |
970d7e83 | 903 | |
1a4d82fc JJ |
904 | // SYS and SYSL generic system instructions. |
905 | def SysCRAsmOperand : AsmOperandClass { | |
906 | let Name = "SysCR"; | |
907 | let ParserMethod = "tryParseSysCROperand"; | |
970d7e83 LB |
908 | } |
909 | ||
1a4d82fc JJ |
910 | def sys_cr_op : Operand<i32> { |
911 | let PrintMethod = "printSysCROperand"; | |
912 | let ParserMatchClass = SysCRAsmOperand; | |
913 | } | |
970d7e83 | 914 | |
1a4d82fc JJ |
915 | class SystemXtI<bit L, string asm> |
916 | : RtSystemI<L, (outs), | |
917 | (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt), | |
918 | asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> { | |
919 | bits<3> op1; | |
920 | bits<4> Cn; | |
921 | bits<4> Cm; | |
922 | bits<3> op2; | |
923 | let Inst{20-19} = 0b01; | |
924 | let Inst{18-16} = op1; | |
925 | let Inst{15-12} = Cn; | |
926 | let Inst{11-8} = Cm; | |
927 | let Inst{7-5} = op2; | |
970d7e83 LB |
928 | } |
929 | ||
1a4d82fc JJ |
930 | class SystemLXtI<bit L, string asm> |
931 | : RtSystemI<L, (outs), | |
932 | (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2), | |
933 | asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> { | |
934 | bits<3> op1; | |
935 | bits<4> Cn; | |
936 | bits<4> Cm; | |
937 | bits<3> op2; | |
938 | let Inst{20-19} = 0b01; | |
939 | let Inst{18-16} = op1; | |
940 | let Inst{15-12} = Cn; | |
941 | let Inst{11-8} = Cm; | |
942 | let Inst{7-5} = op2; | |
943 | } | |
970d7e83 | 944 | |
970d7e83 | 945 | |
1a4d82fc JJ |
946 | // Branch (register) instructions: |
947 | // | |
948 | // case opc of | |
949 | // 0001 blr | |
950 | // 0000 br | |
951 | // 0101 dret | |
952 | // 0100 eret | |
953 | // 0010 ret | |
954 | // otherwise UNDEFINED | |
955 | class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm, | |
956 | string operands, list<dag> pattern> | |
957 | : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> { | |
958 | let Inst{31-25} = 0b1101011; | |
959 | let Inst{24-21} = opc; | |
960 | let Inst{20-16} = 0b11111; | |
961 | let Inst{15-10} = 0b000000; | |
962 | let Inst{4-0} = 0b00000; | |
963 | } | |
964 | ||
965 | class BranchReg<bits<4> opc, string asm, list<dag> pattern> | |
966 | : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> { | |
967 | bits<5> Rn; | |
968 | let Inst{9-5} = Rn; | |
970d7e83 LB |
969 | } |
970 | ||
1a4d82fc JJ |
971 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in |
972 | class SpecialReturn<bits<4> opc, string asm> | |
973 | : BaseBranchReg<opc, (outs), (ins), asm, "", []> { | |
974 | let Inst{9-5} = 0b11111; | |
975 | } | |
970d7e83 | 976 | |
1a4d82fc JJ |
977 | //--- |
978 | // Conditional branch instruction. | |
979 | //--- | |
980 | ||
981 | // Condition code. | |
982 | // 4-bit immediate. Pretty-printed as <cc> | |
983 | def ccode : Operand<i32> { | |
984 | let PrintMethod = "printCondCode"; | |
985 | let ParserMatchClass = CondCode; | |
986 | } | |
987 | def inv_ccode : Operand<i32> { | |
988 | // AL and NV are invalid in the aliases which use inv_ccode | |
989 | let PrintMethod = "printInverseCondCode"; | |
990 | let ParserMatchClass = CondCode; | |
991 | let MCOperandPredicate = [{ | |
992 | return MCOp.isImm() && | |
993 | MCOp.getImm() != AArch64CC::AL && | |
994 | MCOp.getImm() != AArch64CC::NV; | |
995 | }]; | |
996 | } | |
997 | ||
998 | // Conditional branch target. 19-bit immediate. The low two bits of the target | |
999 | // offset are implied zero and so are not part of the immediate. | |
1000 | def PCRelLabel19Operand : AsmOperandClass { | |
1001 | let Name = "PCRelLabel19"; | |
1002 | let DiagnosticType = "InvalidLabel"; | |
1003 | } | |
1004 | def am_brcond : Operand<OtherVT> { | |
1005 | let EncoderMethod = "getCondBranchTargetOpValue"; | |
1006 | let DecoderMethod = "DecodePCRelLabel19"; | |
1007 | let PrintMethod = "printAlignedLabel"; | |
1008 | let ParserMatchClass = PCRelLabel19Operand; | |
970d7e83 LB |
1009 | } |
1010 | ||
1a4d82fc JJ |
1011 | class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target), |
1012 | "b", ".$cond\t$target", "", | |
1013 | [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, | |
1014 | Sched<[WriteBr]> { | |
1015 | let isBranch = 1; | |
1016 | let isTerminator = 1; | |
1017 | let Uses = [NZCV]; | |
970d7e83 | 1018 | |
1a4d82fc JJ |
1019 | bits<4> cond; |
1020 | bits<19> target; | |
1021 | let Inst{31-24} = 0b01010100; | |
1022 | let Inst{23-5} = target; | |
1023 | let Inst{4} = 0; | |
1024 | let Inst{3-0} = cond; | |
970d7e83 LB |
1025 | } |
1026 | ||
1a4d82fc JJ |
1027 | //--- |
1028 | // Compare-and-branch instructions. | |
1029 | //--- | |
1030 | class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node> | |
1031 | : I<(outs), (ins regtype:$Rt, am_brcond:$target), | |
1032 | asm, "\t$Rt, $target", "", | |
1033 | [(node regtype:$Rt, bb:$target)]>, | |
1034 | Sched<[WriteBr]> { | |
1035 | let isBranch = 1; | |
1036 | let isTerminator = 1; | |
970d7e83 | 1037 | |
1a4d82fc JJ |
1038 | bits<5> Rt; |
1039 | bits<19> target; | |
1040 | let Inst{30-25} = 0b011010; | |
1041 | let Inst{24} = op; | |
1042 | let Inst{23-5} = target; | |
1043 | let Inst{4-0} = Rt; | |
970d7e83 LB |
1044 | } |
1045 | ||
1a4d82fc JJ |
1046 | multiclass CmpBranch<bit op, string asm, SDNode node> { |
1047 | def W : BaseCmpBranch<GPR32, op, asm, node> { | |
1048 | let Inst{31} = 0; | |
1049 | } | |
1050 | def X : BaseCmpBranch<GPR64, op, asm, node> { | |
1051 | let Inst{31} = 1; | |
1052 | } | |
1053 | } | |
1054 | ||
1055 | //--- | |
1056 | // Test-bit-and-branch instructions. | |
1057 | //--- | |
1058 | // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of | |
1059 | // the target offset are implied zero and so are not part of the immediate. | |
1060 | def BranchTarget14Operand : AsmOperandClass { | |
1061 | let Name = "BranchTarget14"; | |
1062 | } | |
1063 | def am_tbrcond : Operand<OtherVT> { | |
1064 | let EncoderMethod = "getTestBranchTargetOpValue"; | |
1065 | let PrintMethod = "printAlignedLabel"; | |
1066 | let ParserMatchClass = BranchTarget14Operand; | |
1067 | } | |
1068 | ||
1069 | // AsmOperand classes to emit (or not) special diagnostics | |
1070 | def TBZImm0_31Operand : AsmOperandClass { | |
1071 | let Name = "TBZImm0_31"; | |
1072 | let PredicateMethod = "isImm0_31"; | |
1073 | let RenderMethod = "addImm0_31Operands"; | |
1074 | } | |
1075 | def TBZImm32_63Operand : AsmOperandClass { | |
1076 | let Name = "Imm32_63"; | |
1077 | let DiagnosticType = "InvalidImm0_63"; | |
1078 | } | |
1079 | ||
1080 | class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{ | |
1081 | return (((uint32_t)Imm) < 32); | |
1082 | }]> { | |
1083 | let ParserMatchClass = matcher; | |
1084 | } | |
1085 | ||
1086 | def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>; | |
1087 | def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>; | |
1088 | ||
1089 | def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{ | |
1090 | return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64); | |
1091 | }]> { | |
1092 | let ParserMatchClass = TBZImm32_63Operand; | |
1093 | } | |
1094 | ||
1095 | class BaseTestBranch<RegisterClass regtype, Operand immtype, | |
1096 | bit op, string asm, SDNode node> | |
1097 | : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target), | |
1098 | asm, "\t$Rt, $bit_off, $target", "", | |
1099 | [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>, | |
1100 | Sched<[WriteBr]> { | |
1101 | let isBranch = 1; | |
1102 | let isTerminator = 1; | |
1103 | ||
1104 | bits<5> Rt; | |
1105 | bits<6> bit_off; | |
1106 | bits<14> target; | |
1107 | ||
1108 | let Inst{30-25} = 0b011011; | |
1109 | let Inst{24} = op; | |
1110 | let Inst{23-19} = bit_off{4-0}; | |
1111 | let Inst{18-5} = target; | |
1112 | let Inst{4-0} = Rt; | |
1113 | ||
1114 | let DecoderMethod = "DecodeTestAndBranch"; | |
1115 | } | |
1116 | ||
1117 | multiclass TestBranch<bit op, string asm, SDNode node> { | |
1118 | def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> { | |
1119 | let Inst{31} = 0; | |
1120 | } | |
1121 | ||
1122 | def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> { | |
1123 | let Inst{31} = 1; | |
1124 | } | |
1125 | ||
1126 | // Alias X-reg with 0-31 imm to W-Reg. | |
1127 | def : InstAlias<asm # "\t$Rd, $imm, $target", | |
1128 | (!cast<Instruction>(NAME#"W") GPR32as64:$Rd, | |
1129 | tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>; | |
1130 | def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target), | |
1131 | (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32), | |
1132 | tbz_imm0_31_diag:$imm, bb:$target)>; | |
1133 | } | |
1134 | ||
1135 | //--- | |
1136 | // Unconditional branch (immediate) instructions. | |
1137 | //--- | |
1138 | def BranchTarget26Operand : AsmOperandClass { | |
1139 | let Name = "BranchTarget26"; | |
1140 | let DiagnosticType = "InvalidLabel"; | |
1141 | } | |
1142 | def am_b_target : Operand<OtherVT> { | |
1143 | let EncoderMethod = "getBranchTargetOpValue"; | |
1144 | let PrintMethod = "printAlignedLabel"; | |
1145 | let ParserMatchClass = BranchTarget26Operand; | |
1146 | } | |
1147 | def am_bl_target : Operand<i64> { | |
1148 | let EncoderMethod = "getBranchTargetOpValue"; | |
1149 | let PrintMethod = "printAlignedLabel"; | |
1150 | let ParserMatchClass = BranchTarget26Operand; | |
1151 | } | |
1152 | ||
1153 | class BImm<bit op, dag iops, string asm, list<dag> pattern> | |
1154 | : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> { | |
1155 | bits<26> addr; | |
1156 | let Inst{31} = op; | |
1157 | let Inst{30-26} = 0b00101; | |
1158 | let Inst{25-0} = addr; | |
1159 | ||
1160 | let DecoderMethod = "DecodeUnconditionalBranch"; | |
1161 | } | |
1162 | ||
1163 | class BranchImm<bit op, string asm, list<dag> pattern> | |
1164 | : BImm<op, (ins am_b_target:$addr), asm, pattern>; | |
1165 | class CallImm<bit op, string asm, list<dag> pattern> | |
1166 | : BImm<op, (ins am_bl_target:$addr), asm, pattern>; | |
1167 | ||
1168 | //--- | |
1169 | // Basic one-operand data processing instructions. | |
1170 | //--- | |
1171 | ||
1172 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1173 | class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm, | |
1174 | SDPatternOperator node> | |
1175 | : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "", | |
1176 | [(set regtype:$Rd, (node regtype:$Rn))]>, | |
1177 | Sched<[WriteI, ReadI]> { | |
1178 | bits<5> Rd; | |
1179 | bits<5> Rn; | |
1180 | ||
1181 | let Inst{30-13} = 0b101101011000000000; | |
1182 | let Inst{12-10} = opc; | |
1183 | let Inst{9-5} = Rn; | |
1184 | let Inst{4-0} = Rd; | |
1185 | } | |
1186 | ||
1187 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1188 | multiclass OneOperandData<bits<3> opc, string asm, | |
1189 | SDPatternOperator node = null_frag> { | |
1190 | def Wr : BaseOneOperandData<opc, GPR32, asm, node> { | |
1191 | let Inst{31} = 0; | |
1192 | } | |
1193 | ||
1194 | def Xr : BaseOneOperandData<opc, GPR64, asm, node> { | |
1195 | let Inst{31} = 1; | |
1196 | } | |
1197 | } | |
1198 | ||
1199 | class OneWRegData<bits<3> opc, string asm, SDPatternOperator node> | |
1200 | : BaseOneOperandData<opc, GPR32, asm, node> { | |
1201 | let Inst{31} = 0; | |
1202 | } | |
1203 | ||
1204 | class OneXRegData<bits<3> opc, string asm, SDPatternOperator node> | |
1205 | : BaseOneOperandData<opc, GPR64, asm, node> { | |
1206 | let Inst{31} = 1; | |
1207 | } | |
1208 | ||
1209 | //--- | |
1210 | // Basic two-operand data processing instructions. | |
1211 | //--- | |
1212 | class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm, | |
1213 | list<dag> pattern> | |
1214 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), | |
1215 | asm, "\t$Rd, $Rn, $Rm", "", pattern>, | |
1216 | Sched<[WriteI, ReadI, ReadI]> { | |
1217 | let Uses = [NZCV]; | |
1218 | bits<5> Rd; | |
1219 | bits<5> Rn; | |
1220 | bits<5> Rm; | |
1221 | let Inst{30} = isSub; | |
1222 | let Inst{28-21} = 0b11010000; | |
1223 | let Inst{20-16} = Rm; | |
1224 | let Inst{15-10} = 0; | |
1225 | let Inst{9-5} = Rn; | |
1226 | let Inst{4-0} = Rd; | |
1227 | } | |
1228 | ||
1229 | class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm, | |
1230 | SDNode OpNode> | |
1231 | : BaseBaseAddSubCarry<isSub, regtype, asm, | |
1232 | [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>; | |
1233 | ||
1234 | class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm, | |
1235 | SDNode OpNode> | |
1236 | : BaseBaseAddSubCarry<isSub, regtype, asm, | |
1237 | [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)), | |
1238 | (implicit NZCV)]> { | |
1239 | let Defs = [NZCV]; | |
1240 | } | |
1241 | ||
1242 | multiclass AddSubCarry<bit isSub, string asm, string asm_setflags, | |
1243 | SDNode OpNode, SDNode OpNode_setflags> { | |
1244 | def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> { | |
1245 | let Inst{31} = 0; | |
1246 | let Inst{29} = 0; | |
1247 | } | |
1248 | def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> { | |
1249 | let Inst{31} = 1; | |
1250 | let Inst{29} = 0; | |
1251 | } | |
1252 | ||
1253 | // Sets flags. | |
1254 | def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags, | |
1255 | OpNode_setflags> { | |
1256 | let Inst{31} = 0; | |
1257 | let Inst{29} = 1; | |
1258 | } | |
1259 | def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags, | |
1260 | OpNode_setflags> { | |
1261 | let Inst{31} = 1; | |
1262 | let Inst{29} = 1; | |
1263 | } | |
1264 | } | |
1265 | ||
1266 | class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm, | |
1267 | SDPatternOperator OpNode> | |
1268 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), | |
1269 | asm, "\t$Rd, $Rn, $Rm", "", | |
1270 | [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> { | |
1271 | bits<5> Rd; | |
1272 | bits<5> Rn; | |
1273 | bits<5> Rm; | |
1274 | let Inst{30-21} = 0b0011010110; | |
1275 | let Inst{20-16} = Rm; | |
1276 | let Inst{15-14} = 0b00; | |
1277 | let Inst{13-10} = opc; | |
1278 | let Inst{9-5} = Rn; | |
1279 | let Inst{4-0} = Rd; | |
1280 | } | |
1281 | ||
1282 | class BaseDiv<bit isSigned, RegisterClass regtype, string asm, | |
1283 | SDPatternOperator OpNode> | |
1284 | : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> { | |
1285 | let Inst{10} = isSigned; | |
1286 | } | |
1287 | ||
1288 | multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> { | |
1289 | def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>, | |
1290 | Sched<[WriteID32, ReadID, ReadID]> { | |
1291 | let Inst{31} = 0; | |
1292 | } | |
1293 | def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>, | |
1294 | Sched<[WriteID64, ReadID, ReadID]> { | |
1295 | let Inst{31} = 1; | |
1296 | } | |
1297 | } | |
1298 | ||
1299 | class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm, | |
1300 | SDPatternOperator OpNode = null_frag> | |
1301 | : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>, | |
1302 | Sched<[WriteIS, ReadI]> { | |
1303 | let Inst{11-10} = shift_type; | |
1304 | } | |
1305 | ||
1306 | multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> { | |
1307 | def Wr : BaseShift<shift_type, GPR32, asm> { | |
1308 | let Inst{31} = 0; | |
1309 | } | |
1310 | ||
1311 | def Xr : BaseShift<shift_type, GPR64, asm, OpNode> { | |
1312 | let Inst{31} = 1; | |
1313 | } | |
1314 | ||
1315 | def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)), | |
1316 | (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, | |
1317 | (EXTRACT_SUBREG i64:$Rm, sub_32))>; | |
1318 | ||
1319 | def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))), | |
1320 | (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>; | |
1321 | ||
1322 | def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))), | |
1323 | (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>; | |
1324 | ||
1325 | def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))), | |
1326 | (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>; | |
1327 | } | |
1328 | ||
1329 | class ShiftAlias<string asm, Instruction inst, RegisterClass regtype> | |
1330 | : InstAlias<asm#" $dst, $src1, $src2", | |
1331 | (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>; | |
1332 | ||
1333 | class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype, | |
1334 | RegisterClass addtype, string asm, | |
1335 | list<dag> pattern> | |
1336 | : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra), | |
1337 | asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> { | |
1338 | bits<5> Rd; | |
1339 | bits<5> Rn; | |
1340 | bits<5> Rm; | |
1341 | bits<5> Ra; | |
1342 | let Inst{30-24} = 0b0011011; | |
1343 | let Inst{23-21} = opc; | |
1344 | let Inst{20-16} = Rm; | |
1345 | let Inst{15} = isSub; | |
1346 | let Inst{14-10} = Ra; | |
1347 | let Inst{9-5} = Rn; | |
1348 | let Inst{4-0} = Rd; | |
1349 | } | |
1350 | ||
1351 | multiclass MulAccum<bit isSub, string asm, SDNode AccNode> { | |
1352 | // MADD/MSUB generation is decided by MachineCombiner.cpp | |
1353 | def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, | |
1354 | [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>, | |
1355 | Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> { | |
1356 | let Inst{31} = 0; | |
1357 | } | |
1358 | ||
1359 | def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, | |
1360 | [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>, | |
1361 | Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> { | |
1362 | let Inst{31} = 1; | |
1363 | } | |
1364 | } | |
1365 | ||
1366 | class WideMulAccum<bit isSub, bits<3> opc, string asm, | |
1367 | SDNode AccNode, SDNode ExtNode> | |
1368 | : BaseMulAccum<isSub, opc, GPR32, GPR64, asm, | |
1369 | [(set GPR64:$Rd, (AccNode GPR64:$Ra, | |
1370 | (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>, | |
1371 | Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> { | |
1372 | let Inst{31} = 1; | |
1373 | } | |
1374 | ||
1375 | class MulHi<bits<3> opc, string asm, SDNode OpNode> | |
1376 | : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm), | |
1377 | asm, "\t$Rd, $Rn, $Rm", "", | |
1378 | [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>, | |
1379 | Sched<[WriteIM64, ReadIM, ReadIM]> { | |
1380 | bits<5> Rd; | |
1381 | bits<5> Rn; | |
1382 | bits<5> Rm; | |
1383 | let Inst{31-24} = 0b10011011; | |
1384 | let Inst{23-21} = opc; | |
1385 | let Inst{20-16} = Rm; | |
1386 | let Inst{15} = 0; | |
1387 | let Inst{9-5} = Rn; | |
1388 | let Inst{4-0} = Rd; | |
1389 | ||
1390 | // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 | |
1391 | // (i.e. all bits 1) but is ignored by the processor. | |
1392 | let PostEncoderMethod = "fixMulHigh"; | |
1393 | } | |
1394 | ||
1395 | class MulAccumWAlias<string asm, Instruction inst> | |
1396 | : InstAlias<asm#" $dst, $src1, $src2", | |
1397 | (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>; | |
1398 | class MulAccumXAlias<string asm, Instruction inst> | |
1399 | : InstAlias<asm#" $dst, $src1, $src2", | |
1400 | (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>; | |
1401 | class WideMulAccumAlias<string asm, Instruction inst> | |
1402 | : InstAlias<asm#" $dst, $src1, $src2", | |
1403 | (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>; | |
1404 | ||
1405 | class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg, | |
1406 | SDPatternOperator OpNode, string asm> | |
1407 | : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm), | |
1408 | asm, "\t$Rd, $Rn, $Rm", "", | |
1409 | [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>, | |
1410 | Sched<[WriteISReg, ReadI, ReadISReg]> { | |
1411 | bits<5> Rd; | |
1412 | bits<5> Rn; | |
1413 | bits<5> Rm; | |
1414 | ||
1415 | let Inst{31} = sf; | |
1416 | let Inst{30-21} = 0b0011010110; | |
1417 | let Inst{20-16} = Rm; | |
1418 | let Inst{15-13} = 0b010; | |
1419 | let Inst{12} = C; | |
1420 | let Inst{11-10} = sz; | |
1421 | let Inst{9-5} = Rn; | |
1422 | let Inst{4-0} = Rd; | |
1423 | let Predicates = [HasCRC]; | |
1424 | } | |
1425 | ||
1426 | //--- | |
1427 | // Address generation. | |
1428 | //--- | |
1429 | ||
1430 | class ADRI<bit page, string asm, Operand adr, list<dag> pattern> | |
1431 | : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "", | |
1432 | pattern>, | |
1433 | Sched<[WriteI]> { | |
1434 | bits<5> Xd; | |
1435 | bits<21> label; | |
1436 | let Inst{31} = page; | |
1437 | let Inst{30-29} = label{1-0}; | |
1438 | let Inst{28-24} = 0b10000; | |
1439 | let Inst{23-5} = label{20-2}; | |
1440 | let Inst{4-0} = Xd; | |
1441 | ||
1442 | let DecoderMethod = "DecodeAdrInstruction"; | |
1443 | } | |
1444 | ||
1445 | //--- | |
1446 | // Move immediate. | |
1447 | //--- | |
1448 | ||
1449 | def movimm32_imm : Operand<i32> { | |
1450 | let ParserMatchClass = Imm0_65535Operand; | |
1451 | let EncoderMethod = "getMoveWideImmOpValue"; | |
1452 | let PrintMethod = "printHexImm"; | |
1453 | } | |
1454 | def movimm32_shift : Operand<i32> { | |
1455 | let PrintMethod = "printShifter"; | |
1456 | let ParserMatchClass = MovImm32ShifterOperand; | |
1457 | } | |
1458 | def movimm64_shift : Operand<i32> { | |
1459 | let PrintMethod = "printShifter"; | |
1460 | let ParserMatchClass = MovImm64ShifterOperand; | |
1461 | } | |
1462 | ||
1463 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1464 | class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter, | |
1465 | string asm> | |
1466 | : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift), | |
1467 | asm, "\t$Rd, $imm$shift", "", []>, | |
1468 | Sched<[WriteImm]> { | |
1469 | bits<5> Rd; | |
1470 | bits<16> imm; | |
1471 | bits<6> shift; | |
1472 | let Inst{30-29} = opc; | |
1473 | let Inst{28-23} = 0b100101; | |
1474 | let Inst{22-21} = shift{5-4}; | |
1475 | let Inst{20-5} = imm; | |
1476 | let Inst{4-0} = Rd; | |
1477 | ||
1478 | let DecoderMethod = "DecodeMoveImmInstruction"; | |
1479 | } | |
1480 | ||
1481 | multiclass MoveImmediate<bits<2> opc, string asm> { | |
1482 | def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> { | |
1483 | let Inst{31} = 0; | |
1484 | } | |
1485 | ||
1486 | def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> { | |
1487 | let Inst{31} = 1; | |
1488 | } | |
1489 | } | |
1490 | ||
1491 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1492 | class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter, | |
1493 | string asm> | |
1494 | : I<(outs regtype:$Rd), | |
1495 | (ins regtype:$src, movimm32_imm:$imm, shifter:$shift), | |
1496 | asm, "\t$Rd, $imm$shift", "$src = $Rd", []>, | |
1497 | Sched<[WriteI, ReadI]> { | |
1498 | bits<5> Rd; | |
1499 | bits<16> imm; | |
1500 | bits<6> shift; | |
1501 | let Inst{30-29} = opc; | |
1502 | let Inst{28-23} = 0b100101; | |
1503 | let Inst{22-21} = shift{5-4}; | |
1504 | let Inst{20-5} = imm; | |
1505 | let Inst{4-0} = Rd; | |
1506 | ||
1507 | let DecoderMethod = "DecodeMoveImmInstruction"; | |
1508 | } | |
1509 | ||
1510 | multiclass InsertImmediate<bits<2> opc, string asm> { | |
1511 | def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> { | |
1512 | let Inst{31} = 0; | |
1513 | } | |
1514 | ||
1515 | def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> { | |
1516 | let Inst{31} = 1; | |
1517 | } | |
1518 | } | |
1519 | ||
1520 | //--- | |
1521 | // Add/Subtract | |
1522 | //--- | |
1523 | ||
1524 | class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype, | |
1525 | RegisterClass srcRegtype, addsub_shifted_imm immtype, | |
1526 | string asm, SDPatternOperator OpNode> | |
1527 | : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm), | |
1528 | asm, "\t$Rd, $Rn, $imm", "", | |
1529 | [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>, | |
1530 | Sched<[WriteI, ReadI]> { | |
1531 | bits<5> Rd; | |
1532 | bits<5> Rn; | |
1533 | bits<14> imm; | |
1534 | let Inst{30} = isSub; | |
1535 | let Inst{29} = setFlags; | |
1536 | let Inst{28-24} = 0b10001; | |
1537 | let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12 | |
1538 | let Inst{21-10} = imm{11-0}; | |
1539 | let Inst{9-5} = Rn; | |
1540 | let Inst{4-0} = Rd; | |
1541 | let DecoderMethod = "DecodeBaseAddSubImm"; | |
1542 | } | |
1543 | ||
1544 | class BaseAddSubRegPseudo<RegisterClass regtype, | |
1545 | SDPatternOperator OpNode> | |
1546 | : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), | |
1547 | [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>, | |
1548 | Sched<[WriteI, ReadI, ReadI]>; | |
1549 | ||
1550 | class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype, | |
1551 | arith_shifted_reg shifted_regtype, string asm, | |
1552 | SDPatternOperator OpNode> | |
1553 | : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm), | |
1554 | asm, "\t$Rd, $Rn, $Rm", "", | |
1555 | [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>, | |
1556 | Sched<[WriteISReg, ReadI, ReadISReg]> { | |
1557 | // The operands are in order to match the 'addr' MI operands, so we | |
1558 | // don't need an encoder method and by-name matching. Just use the default | |
1559 | // in-order handling. Since we're using by-order, make sure the names | |
1560 | // do not match. | |
1561 | bits<5> dst; | |
1562 | bits<5> src1; | |
1563 | bits<5> src2; | |
1564 | bits<8> shift; | |
1565 | let Inst{30} = isSub; | |
1566 | let Inst{29} = setFlags; | |
1567 | let Inst{28-24} = 0b01011; | |
1568 | let Inst{23-22} = shift{7-6}; | |
1569 | let Inst{21} = 0; | |
1570 | let Inst{20-16} = src2; | |
1571 | let Inst{15-10} = shift{5-0}; | |
1572 | let Inst{9-5} = src1; | |
1573 | let Inst{4-0} = dst; | |
1574 | ||
1575 | let DecoderMethod = "DecodeThreeAddrSRegInstruction"; | |
1576 | } | |
1577 | ||
1578 | class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype, | |
1579 | RegisterClass src1Regtype, Operand src2Regtype, | |
1580 | string asm, SDPatternOperator OpNode> | |
1581 | : I<(outs dstRegtype:$R1), | |
1582 | (ins src1Regtype:$R2, src2Regtype:$R3), | |
1583 | asm, "\t$R1, $R2, $R3", "", | |
1584 | [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>, | |
1585 | Sched<[WriteIEReg, ReadI, ReadIEReg]> { | |
1586 | bits<5> Rd; | |
1587 | bits<5> Rn; | |
1588 | bits<5> Rm; | |
1589 | bits<6> ext; | |
1590 | let Inst{30} = isSub; | |
1591 | let Inst{29} = setFlags; | |
1592 | let Inst{28-24} = 0b01011; | |
1593 | let Inst{23-21} = 0b001; | |
1594 | let Inst{20-16} = Rm; | |
1595 | let Inst{15-13} = ext{5-3}; | |
1596 | let Inst{12-10} = ext{2-0}; | |
1597 | let Inst{9-5} = Rn; | |
1598 | let Inst{4-0} = Rd; | |
1599 | ||
1600 | let DecoderMethod = "DecodeAddSubERegInstruction"; | |
1601 | } | |
1602 | ||
1603 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1604 | class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype, | |
1605 | RegisterClass src1Regtype, RegisterClass src2Regtype, | |
1606 | Operand ext_op, string asm> | |
1607 | : I<(outs dstRegtype:$Rd), | |
1608 | (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext), | |
1609 | asm, "\t$Rd, $Rn, $Rm$ext", "", []>, | |
1610 | Sched<[WriteIEReg, ReadI, ReadIEReg]> { | |
1611 | bits<5> Rd; | |
1612 | bits<5> Rn; | |
1613 | bits<5> Rm; | |
1614 | bits<6> ext; | |
1615 | let Inst{30} = isSub; | |
1616 | let Inst{29} = setFlags; | |
1617 | let Inst{28-24} = 0b01011; | |
1618 | let Inst{23-21} = 0b001; | |
1619 | let Inst{20-16} = Rm; | |
1620 | let Inst{15} = ext{5}; | |
1621 | let Inst{12-10} = ext{2-0}; | |
1622 | let Inst{9-5} = Rn; | |
1623 | let Inst{4-0} = Rd; | |
1624 | ||
1625 | let DecoderMethod = "DecodeAddSubERegInstruction"; | |
1626 | } | |
1627 | ||
1628 | // Aliases for register+register add/subtract. | |
1629 | class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype, | |
1630 | RegisterClass src1Regtype, RegisterClass src2Regtype, | |
1631 | int shiftExt> | |
1632 | : InstAlias<asm#" $dst, $src1, $src2", | |
1633 | (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2, | |
1634 | shiftExt)>; | |
1635 | ||
1636 | multiclass AddSub<bit isSub, string mnemonic, | |
1637 | SDPatternOperator OpNode = null_frag> { | |
1638 | let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in { | |
1639 | // Add/Subtract immediate | |
1640 | def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32, | |
1641 | mnemonic, OpNode> { | |
1642 | let Inst{31} = 0; | |
1643 | } | |
1644 | def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64, | |
1645 | mnemonic, OpNode> { | |
1646 | let Inst{31} = 1; | |
1647 | } | |
1648 | ||
1649 | // Add/Subtract register - Only used for CodeGen | |
1650 | def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>; | |
1651 | def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>; | |
1652 | ||
1653 | // Add/Subtract shifted register | |
1654 | def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic, | |
1655 | OpNode> { | |
1656 | let Inst{31} = 0; | |
1657 | } | |
1658 | def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic, | |
1659 | OpNode> { | |
1660 | let Inst{31} = 1; | |
1661 | } | |
1662 | } | |
1663 | ||
1664 | // Add/Subtract extended register | |
1665 | let AddedComplexity = 1, hasSideEffects = 0 in { | |
1666 | def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp, | |
1667 | arith_extended_reg32<i32>, mnemonic, OpNode> { | |
1668 | let Inst{31} = 0; | |
1669 | } | |
1670 | def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp, | |
1671 | arith_extended_reg32to64<i64>, mnemonic, OpNode> { | |
1672 | let Inst{31} = 1; | |
1673 | } | |
1674 | } | |
1675 | ||
1676 | def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64, | |
1677 | arith_extendlsl64, mnemonic> { | |
1678 | // UXTX and SXTX only. | |
1679 | let Inst{14-13} = 0b11; | |
1680 | let Inst{31} = 1; | |
1681 | } | |
1682 | ||
1683 | // Register/register aliases with no shift when SP is not used. | |
1684 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"), | |
1685 | GPR32, GPR32, GPR32, 0>; | |
1686 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"), | |
1687 | GPR64, GPR64, GPR64, 0>; | |
1688 | ||
1689 | // Register/register aliases with no shift when either the destination or | |
1690 | // first source register is SP. | |
1691 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"), | |
1692 | GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0 | |
1693 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"), | |
1694 | GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0 | |
1695 | def : AddSubRegAlias<mnemonic, | |
1696 | !cast<Instruction>(NAME#"Xrx64"), | |
1697 | GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0 | |
1698 | def : AddSubRegAlias<mnemonic, | |
1699 | !cast<Instruction>(NAME#"Xrx64"), | |
1700 | GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0 | |
1701 | } | |
1702 | ||
1703 | multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp> { | |
1704 | let isCompare = 1, Defs = [NZCV] in { | |
1705 | // Add/Subtract immediate | |
1706 | def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32, | |
1707 | mnemonic, OpNode> { | |
1708 | let Inst{31} = 0; | |
1709 | } | |
1710 | def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64, | |
1711 | mnemonic, OpNode> { | |
1712 | let Inst{31} = 1; | |
1713 | } | |
1714 | ||
1715 | // Add/Subtract register | |
1716 | def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>; | |
1717 | def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>; | |
1718 | ||
1719 | // Add/Subtract shifted register | |
1720 | def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic, | |
1721 | OpNode> { | |
1722 | let Inst{31} = 0; | |
1723 | } | |
1724 | def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic, | |
1725 | OpNode> { | |
1726 | let Inst{31} = 1; | |
1727 | } | |
1728 | ||
1729 | // Add/Subtract extended register | |
1730 | let AddedComplexity = 1 in { | |
1731 | def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp, | |
1732 | arith_extended_reg32<i32>, mnemonic, OpNode> { | |
1733 | let Inst{31} = 0; | |
1734 | } | |
1735 | def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp, | |
1736 | arith_extended_reg32<i64>, mnemonic, OpNode> { | |
1737 | let Inst{31} = 1; | |
1738 | } | |
1739 | } | |
1740 | ||
1741 | def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64, | |
1742 | arith_extendlsl64, mnemonic> { | |
1743 | // UXTX and SXTX only. | |
1744 | let Inst{14-13} = 0b11; | |
1745 | let Inst{31} = 1; | |
1746 | } | |
1747 | } // Defs = [NZCV] | |
1748 | ||
1749 | // Compare aliases | |
1750 | def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Wri") | |
1751 | WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>; | |
1752 | def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Xri") | |
1753 | XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>; | |
1754 | def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx") | |
1755 | WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>; | |
1756 | def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx") | |
1757 | XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>; | |
1758 | def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64") | |
1759 | XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>; | |
1760 | def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs") | |
1761 | WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>; | |
1762 | def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs") | |
1763 | XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>; | |
1764 | ||
1765 | // Compare shorthands | |
1766 | def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrs") | |
1767 | WZR, GPR32:$src1, GPR32:$src2, 0), 5>; | |
1768 | def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrs") | |
1769 | XZR, GPR64:$src1, GPR64:$src2, 0), 5>; | |
1770 | def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrx") | |
1771 | WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>; | |
1772 | def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrx64") | |
1773 | XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>; | |
1774 | ||
1775 | // Register/register aliases with no shift when SP is not used. | |
1776 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"), | |
1777 | GPR32, GPR32, GPR32, 0>; | |
1778 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"), | |
1779 | GPR64, GPR64, GPR64, 0>; | |
1780 | ||
1781 | // Register/register aliases with no shift when the first source register | |
1782 | // is SP. | |
1783 | def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"), | |
1784 | GPR32, GPR32sponly, GPR32, 16>; // UXTW #0 | |
1785 | def : AddSubRegAlias<mnemonic, | |
1786 | !cast<Instruction>(NAME#"Xrx64"), | |
1787 | GPR64, GPR64sponly, GPR64, 24>; // UXTX #0 | |
1788 | } | |
1789 | ||
1790 | //--- | |
1791 | // Extract | |
1792 | //--- | |
1793 | def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, | |
1794 | SDTCisPtrTy<3>]>; | |
1795 | def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>; | |
1796 | ||
1797 | class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm, | |
1798 | list<dag> patterns> | |
1799 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm), | |
1800 | asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>, | |
1801 | Sched<[WriteExtr, ReadExtrHi]> { | |
1802 | bits<5> Rd; | |
1803 | bits<5> Rn; | |
1804 | bits<5> Rm; | |
1805 | bits<6> imm; | |
1806 | ||
1807 | let Inst{30-23} = 0b00100111; | |
1808 | let Inst{21} = 0; | |
1809 | let Inst{20-16} = Rm; | |
1810 | let Inst{15-10} = imm; | |
1811 | let Inst{9-5} = Rn; | |
1812 | let Inst{4-0} = Rd; | |
1813 | } | |
1814 | ||
1815 | multiclass ExtractImm<string asm> { | |
1816 | def Wrri : BaseExtractImm<GPR32, imm0_31, asm, | |
1817 | [(set GPR32:$Rd, | |
1818 | (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> { | |
1819 | let Inst{31} = 0; | |
1820 | let Inst{22} = 0; | |
1821 | // imm<5> must be zero. | |
1822 | let imm{5} = 0; | |
1823 | } | |
1824 | def Xrri : BaseExtractImm<GPR64, imm0_63, asm, | |
1825 | [(set GPR64:$Rd, | |
1826 | (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> { | |
1827 | ||
1828 | let Inst{31} = 1; | |
1829 | let Inst{22} = 1; | |
1830 | } | |
1831 | } | |
1832 | ||
1833 | //--- | |
1834 | // Bitfield | |
1835 | //--- | |
1836 | ||
1837 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1838 | class BaseBitfieldImm<bits<2> opc, | |
1839 | RegisterClass regtype, Operand imm_type, string asm> | |
1840 | : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms), | |
1841 | asm, "\t$Rd, $Rn, $immr, $imms", "", []>, | |
1842 | Sched<[WriteIS, ReadI]> { | |
1843 | bits<5> Rd; | |
1844 | bits<5> Rn; | |
1845 | bits<6> immr; | |
1846 | bits<6> imms; | |
1847 | ||
1848 | let Inst{30-29} = opc; | |
1849 | let Inst{28-23} = 0b100110; | |
1850 | let Inst{21-16} = immr; | |
1851 | let Inst{15-10} = imms; | |
1852 | let Inst{9-5} = Rn; | |
1853 | let Inst{4-0} = Rd; | |
1854 | } | |
1855 | ||
1856 | multiclass BitfieldImm<bits<2> opc, string asm> { | |
1857 | def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> { | |
1858 | let Inst{31} = 0; | |
1859 | let Inst{22} = 0; | |
1860 | // imms<5> and immr<5> must be zero, else ReservedValue(). | |
1861 | let Inst{21} = 0; | |
1862 | let Inst{15} = 0; | |
1863 | } | |
1864 | def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> { | |
1865 | let Inst{31} = 1; | |
1866 | let Inst{22} = 1; | |
1867 | } | |
1868 | } | |
1869 | ||
1870 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
1871 | class BaseBitfieldImmWith2RegArgs<bits<2> opc, | |
1872 | RegisterClass regtype, Operand imm_type, string asm> | |
1873 | : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr, | |
1874 | imm_type:$imms), | |
1875 | asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>, | |
1876 | Sched<[WriteIS, ReadI]> { | |
1877 | bits<5> Rd; | |
1878 | bits<5> Rn; | |
1879 | bits<6> immr; | |
1880 | bits<6> imms; | |
1881 | ||
1882 | let Inst{30-29} = opc; | |
1883 | let Inst{28-23} = 0b100110; | |
1884 | let Inst{21-16} = immr; | |
1885 | let Inst{15-10} = imms; | |
1886 | let Inst{9-5} = Rn; | |
1887 | let Inst{4-0} = Rd; | |
1888 | } | |
1889 | ||
1890 | multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> { | |
1891 | def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> { | |
1892 | let Inst{31} = 0; | |
1893 | let Inst{22} = 0; | |
1894 | // imms<5> and immr<5> must be zero, else ReservedValue(). | |
1895 | let Inst{21} = 0; | |
1896 | let Inst{15} = 0; | |
1897 | } | |
1898 | def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> { | |
1899 | let Inst{31} = 1; | |
1900 | let Inst{22} = 1; | |
1901 | } | |
1902 | } | |
1903 | ||
1904 | //--- | |
1905 | // Logical | |
1906 | //--- | |
1907 | ||
1908 | // Logical (immediate) | |
1909 | class BaseLogicalImm<bits<2> opc, RegisterClass dregtype, | |
1910 | RegisterClass sregtype, Operand imm_type, string asm, | |
1911 | list<dag> pattern> | |
1912 | : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm), | |
1913 | asm, "\t$Rd, $Rn, $imm", "", pattern>, | |
1914 | Sched<[WriteI, ReadI]> { | |
1915 | bits<5> Rd; | |
1916 | bits<5> Rn; | |
1917 | bits<13> imm; | |
1918 | let Inst{30-29} = opc; | |
1919 | let Inst{28-23} = 0b100100; | |
1920 | let Inst{22} = imm{12}; | |
1921 | let Inst{21-16} = imm{11-6}; | |
1922 | let Inst{15-10} = imm{5-0}; | |
1923 | let Inst{9-5} = Rn; | |
1924 | let Inst{4-0} = Rd; | |
1925 | ||
1926 | let DecoderMethod = "DecodeLogicalImmInstruction"; | |
1927 | } | |
1928 | ||
1929 | // Logical (shifted register) | |
1930 | class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype, | |
1931 | logical_shifted_reg shifted_regtype, string asm, | |
1932 | list<dag> pattern> | |
1933 | : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm), | |
1934 | asm, "\t$Rd, $Rn, $Rm", "", pattern>, | |
1935 | Sched<[WriteISReg, ReadI, ReadISReg]> { | |
1936 | // The operands are in order to match the 'addr' MI operands, so we | |
1937 | // don't need an encoder method and by-name matching. Just use the default | |
1938 | // in-order handling. Since we're using by-order, make sure the names | |
1939 | // do not match. | |
1940 | bits<5> dst; | |
1941 | bits<5> src1; | |
1942 | bits<5> src2; | |
1943 | bits<8> shift; | |
1944 | let Inst{30-29} = opc; | |
1945 | let Inst{28-24} = 0b01010; | |
1946 | let Inst{23-22} = shift{7-6}; | |
1947 | let Inst{21} = N; | |
1948 | let Inst{20-16} = src2; | |
1949 | let Inst{15-10} = shift{5-0}; | |
1950 | let Inst{9-5} = src1; | |
1951 | let Inst{4-0} = dst; | |
1952 | ||
1953 | let DecoderMethod = "DecodeThreeAddrSRegInstruction"; | |
1954 | } | |
1955 | ||
1956 | // Aliases for register+register logical instructions. | |
1957 | class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype> | |
1958 | : InstAlias<asm#" $dst, $src1, $src2", | |
1959 | (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>; | |
1960 | ||
1961 | multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode, | |
1962 | string Alias> { | |
1963 | let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in | |
1964 | def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic, | |
1965 | [(set GPR32sp:$Rd, (OpNode GPR32:$Rn, | |
1966 | logical_imm32:$imm))]> { | |
1967 | let Inst{31} = 0; | |
1968 | let Inst{22} = 0; // 64-bit version has an additional bit of immediate. | |
1969 | } | |
1970 | let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in | |
1971 | def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic, | |
1972 | [(set GPR64sp:$Rd, (OpNode GPR64:$Rn, | |
1973 | logical_imm64:$imm))]> { | |
1974 | let Inst{31} = 1; | |
1975 | } | |
1976 | ||
1977 | def : InstAlias<Alias # " $Rd, $Rn, $imm", | |
1978 | (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn, | |
1979 | logical_imm32_not:$imm), 0>; | |
1980 | def : InstAlias<Alias # " $Rd, $Rn, $imm", | |
1981 | (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn, | |
1982 | logical_imm64_not:$imm), 0>; | |
1983 | } | |
1984 | ||
1985 | multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode, | |
1986 | string Alias> { | |
1987 | let isCompare = 1, Defs = [NZCV] in { | |
1988 | def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic, | |
1989 | [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> { | |
1990 | let Inst{31} = 0; | |
1991 | let Inst{22} = 0; // 64-bit version has an additional bit of immediate. | |
1992 | } | |
1993 | def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic, | |
1994 | [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> { | |
1995 | let Inst{31} = 1; | |
1996 | } | |
1997 | } // end Defs = [NZCV] | |
1998 | ||
1999 | def : InstAlias<Alias # " $Rd, $Rn, $imm", | |
2000 | (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn, | |
2001 | logical_imm32_not:$imm), 0>; | |
2002 | def : InstAlias<Alias # " $Rd, $Rn, $imm", | |
2003 | (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn, | |
2004 | logical_imm64_not:$imm), 0>; | |
2005 | } | |
2006 | ||
2007 | class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode> | |
2008 | : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), | |
2009 | [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>, | |
2010 | Sched<[WriteI, ReadI, ReadI]>; | |
2011 | ||
2012 | // Split from LogicalImm as not all instructions have both. | |
2013 | multiclass LogicalReg<bits<2> opc, bit N, string mnemonic, | |
2014 | SDPatternOperator OpNode> { | |
2015 | let isReMaterializable = 1, isAsCheapAsAMove = 1 in { | |
2016 | def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>; | |
2017 | def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>; | |
2018 | } | |
2019 | ||
2020 | def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, | |
2021 | [(set GPR32:$Rd, (OpNode GPR32:$Rn, | |
2022 | logical_shifted_reg32:$Rm))]> { | |
2023 | let Inst{31} = 0; | |
2024 | } | |
2025 | def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, | |
2026 | [(set GPR64:$Rd, (OpNode GPR64:$Rn, | |
2027 | logical_shifted_reg64:$Rm))]> { | |
2028 | let Inst{31} = 1; | |
2029 | } | |
2030 | ||
2031 | def : LogicalRegAlias<mnemonic, | |
2032 | !cast<Instruction>(NAME#"Wrs"), GPR32>; | |
2033 | def : LogicalRegAlias<mnemonic, | |
2034 | !cast<Instruction>(NAME#"Xrs"), GPR64>; | |
2035 | } | |
2036 | ||
2037 | // Split from LogicalReg to allow setting NZCV Defs | |
2038 | multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic, | |
2039 | SDPatternOperator OpNode = null_frag> { | |
2040 | let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
2041 | def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>; | |
2042 | def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>; | |
2043 | ||
2044 | def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, | |
2045 | [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> { | |
2046 | let Inst{31} = 0; | |
2047 | } | |
2048 | def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, | |
2049 | [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> { | |
2050 | let Inst{31} = 1; | |
2051 | } | |
2052 | } // Defs = [NZCV] | |
2053 | ||
2054 | def : LogicalRegAlias<mnemonic, | |
2055 | !cast<Instruction>(NAME#"Wrs"), GPR32>; | |
2056 | def : LogicalRegAlias<mnemonic, | |
2057 | !cast<Instruction>(NAME#"Xrs"), GPR64>; | |
2058 | } | |
2059 | ||
2060 | //--- | |
2061 | // Conditionally set flags | |
2062 | //--- | |
2063 | ||
2064 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
2065 | class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm> | |
2066 | : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond), | |
2067 | asm, "\t$Rn, $imm, $nzcv, $cond", "", []>, | |
2068 | Sched<[WriteI, ReadI]> { | |
2069 | let Uses = [NZCV]; | |
2070 | let Defs = [NZCV]; | |
2071 | ||
2072 | bits<5> Rn; | |
2073 | bits<5> imm; | |
2074 | bits<4> nzcv; | |
2075 | bits<4> cond; | |
2076 | ||
2077 | let Inst{30} = op; | |
2078 | let Inst{29-21} = 0b111010010; | |
2079 | let Inst{20-16} = imm; | |
2080 | let Inst{15-12} = cond; | |
2081 | let Inst{11-10} = 0b10; | |
2082 | let Inst{9-5} = Rn; | |
2083 | let Inst{4} = 0b0; | |
2084 | let Inst{3-0} = nzcv; | |
2085 | } | |
2086 | ||
2087 | multiclass CondSetFlagsImm<bit op, string asm> { | |
2088 | def Wi : BaseCondSetFlagsImm<op, GPR32, asm> { | |
2089 | let Inst{31} = 0; | |
2090 | } | |
2091 | def Xi : BaseCondSetFlagsImm<op, GPR64, asm> { | |
2092 | let Inst{31} = 1; | |
2093 | } | |
2094 | } | |
2095 | ||
2096 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
2097 | class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm> | |
2098 | : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond), | |
2099 | asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>, | |
2100 | Sched<[WriteI, ReadI, ReadI]> { | |
2101 | let Uses = [NZCV]; | |
2102 | let Defs = [NZCV]; | |
2103 | ||
2104 | bits<5> Rn; | |
2105 | bits<5> Rm; | |
2106 | bits<4> nzcv; | |
2107 | bits<4> cond; | |
2108 | ||
2109 | let Inst{30} = op; | |
2110 | let Inst{29-21} = 0b111010010; | |
2111 | let Inst{20-16} = Rm; | |
2112 | let Inst{15-12} = cond; | |
2113 | let Inst{11-10} = 0b00; | |
2114 | let Inst{9-5} = Rn; | |
2115 | let Inst{4} = 0b0; | |
2116 | let Inst{3-0} = nzcv; | |
2117 | } | |
2118 | ||
2119 | multiclass CondSetFlagsReg<bit op, string asm> { | |
2120 | def Wr : BaseCondSetFlagsReg<op, GPR32, asm> { | |
2121 | let Inst{31} = 0; | |
2122 | } | |
2123 | def Xr : BaseCondSetFlagsReg<op, GPR64, asm> { | |
2124 | let Inst{31} = 1; | |
2125 | } | |
2126 | } | |
2127 | ||
2128 | //--- | |
2129 | // Conditional select | |
2130 | //--- | |
2131 | ||
2132 | class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm> | |
2133 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond), | |
2134 | asm, "\t$Rd, $Rn, $Rm, $cond", "", | |
2135 | [(set regtype:$Rd, | |
2136 | (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>, | |
2137 | Sched<[WriteI, ReadI, ReadI]> { | |
2138 | let Uses = [NZCV]; | |
2139 | ||
2140 | bits<5> Rd; | |
2141 | bits<5> Rn; | |
2142 | bits<5> Rm; | |
2143 | bits<4> cond; | |
2144 | ||
2145 | let Inst{30} = op; | |
2146 | let Inst{29-21} = 0b011010100; | |
2147 | let Inst{20-16} = Rm; | |
2148 | let Inst{15-12} = cond; | |
2149 | let Inst{11-10} = op2; | |
2150 | let Inst{9-5} = Rn; | |
2151 | let Inst{4-0} = Rd; | |
2152 | } | |
2153 | ||
2154 | multiclass CondSelect<bit op, bits<2> op2, string asm> { | |
2155 | def Wr : BaseCondSelect<op, op2, GPR32, asm> { | |
2156 | let Inst{31} = 0; | |
2157 | } | |
2158 | def Xr : BaseCondSelect<op, op2, GPR64, asm> { | |
2159 | let Inst{31} = 1; | |
2160 | } | |
2161 | } | |
2162 | ||
2163 | class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm, | |
2164 | PatFrag frag> | |
2165 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond), | |
2166 | asm, "\t$Rd, $Rn, $Rm, $cond", "", | |
2167 | [(set regtype:$Rd, | |
2168 | (AArch64csel regtype:$Rn, (frag regtype:$Rm), | |
2169 | (i32 imm:$cond), NZCV))]>, | |
2170 | Sched<[WriteI, ReadI, ReadI]> { | |
2171 | let Uses = [NZCV]; | |
2172 | ||
2173 | bits<5> Rd; | |
2174 | bits<5> Rn; | |
2175 | bits<5> Rm; | |
2176 | bits<4> cond; | |
2177 | ||
2178 | let Inst{30} = op; | |
2179 | let Inst{29-21} = 0b011010100; | |
2180 | let Inst{20-16} = Rm; | |
2181 | let Inst{15-12} = cond; | |
2182 | let Inst{11-10} = op2; | |
2183 | let Inst{9-5} = Rn; | |
2184 | let Inst{4-0} = Rd; | |
2185 | } | |
2186 | ||
2187 | def inv_cond_XFORM : SDNodeXForm<imm, [{ | |
2188 | AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue()); | |
2189 | return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), MVT::i32); | |
2190 | }]>; | |
2191 | ||
2192 | multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> { | |
2193 | def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> { | |
2194 | let Inst{31} = 0; | |
2195 | } | |
2196 | def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> { | |
2197 | let Inst{31} = 1; | |
2198 | } | |
2199 | ||
2200 | def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV), | |
2201 | (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm, | |
2202 | (inv_cond_XFORM imm:$cond))>; | |
2203 | ||
2204 | def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV), | |
2205 | (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm, | |
2206 | (inv_cond_XFORM imm:$cond))>; | |
2207 | } | |
2208 | ||
2209 | //--- | |
2210 | // Special Mask Value | |
2211 | //--- | |
2212 | def maski8_or_more : Operand<i32>, | |
2213 | ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> { | |
2214 | } | |
2215 | def maski16_or_more : Operand<i32>, | |
2216 | ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> { | |
2217 | } | |
2218 | ||
2219 | ||
2220 | //--- | |
2221 | // Load/store | |
2222 | //--- | |
2223 | ||
2224 | // (unsigned immediate) | |
2225 | // Indexed for 8-bit registers. offset is in range [0,4095]. | |
2226 | def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>; | |
2227 | def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>; | |
2228 | def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>; | |
2229 | def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>; | |
2230 | def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>; | |
2231 | ||
2232 | class UImm12OffsetOperand<int Scale> : AsmOperandClass { | |
2233 | let Name = "UImm12Offset" # Scale; | |
2234 | let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">"; | |
2235 | let PredicateMethod = "isUImm12Offset<" # Scale # ">"; | |
2236 | let DiagnosticType = "InvalidMemoryIndexed" # Scale; | |
2237 | } | |
2238 | ||
2239 | def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>; | |
2240 | def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>; | |
2241 | def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>; | |
2242 | def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>; | |
2243 | def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>; | |
2244 | ||
2245 | class uimm12_scaled<int Scale> : Operand<i64> { | |
2246 | let ParserMatchClass | |
2247 | = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand"); | |
2248 | let EncoderMethod | |
2249 | = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">"; | |
2250 | let PrintMethod = "printUImm12Offset<" # Scale # ">"; | |
2251 | } | |
2252 | ||
2253 | def uimm12s1 : uimm12_scaled<1>; | |
2254 | def uimm12s2 : uimm12_scaled<2>; | |
2255 | def uimm12s4 : uimm12_scaled<4>; | |
2256 | def uimm12s8 : uimm12_scaled<8>; | |
2257 | def uimm12s16 : uimm12_scaled<16>; | |
2258 | ||
2259 | class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, | |
2260 | string asm, list<dag> pattern> | |
2261 | : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> { | |
2262 | bits<5> Rt; | |
2263 | ||
2264 | bits<5> Rn; | |
2265 | bits<12> offset; | |
2266 | ||
2267 | let Inst{31-30} = sz; | |
2268 | let Inst{29-27} = 0b111; | |
2269 | let Inst{26} = V; | |
2270 | let Inst{25-24} = 0b01; | |
2271 | let Inst{23-22} = opc; | |
2272 | let Inst{21-10} = offset; | |
2273 | let Inst{9-5} = Rn; | |
2274 | let Inst{4-0} = Rt; | |
2275 | ||
2276 | let DecoderMethod = "DecodeUnsignedLdStInstruction"; | |
2277 | } | |
2278 | ||
2279 | multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2280 | Operand indextype, string asm, list<dag> pattern> { | |
2281 | let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
2282 | def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt), | |
2283 | (ins GPR64sp:$Rn, indextype:$offset), | |
2284 | asm, pattern>, | |
2285 | Sched<[WriteLD]>; | |
2286 | ||
2287 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2288 | (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>; | |
2289 | } | |
2290 | ||
2291 | multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2292 | Operand indextype, string asm, list<dag> pattern> { | |
2293 | let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
2294 | def ui : BaseLoadStoreUI<sz, V, opc, (outs), | |
2295 | (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset), | |
2296 | asm, pattern>, | |
2297 | Sched<[WriteST]>; | |
2298 | ||
2299 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2300 | (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>; | |
2301 | } | |
2302 | ||
2303 | def PrefetchOperand : AsmOperandClass { | |
2304 | let Name = "Prefetch"; | |
2305 | let ParserMethod = "tryParsePrefetch"; | |
2306 | } | |
2307 | def prfop : Operand<i32> { | |
2308 | let PrintMethod = "printPrefetchOp"; | |
2309 | let ParserMatchClass = PrefetchOperand; | |
2310 | } | |
2311 | ||
2312 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in | |
2313 | class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat> | |
2314 | : BaseLoadStoreUI<sz, V, opc, | |
2315 | (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset), | |
2316 | asm, pat>, | |
2317 | Sched<[WriteLD]>; | |
2318 | ||
2319 | //--- | |
2320 | // Load literal | |
2321 | //--- | |
2322 | ||
2323 | // Load literal address: 19-bit immediate. The low two bits of the target | |
2324 | // offset are implied zero and so are not part of the immediate. | |
2325 | def am_ldrlit : Operand<OtherVT> { | |
2326 | let EncoderMethod = "getLoadLiteralOpValue"; | |
2327 | let DecoderMethod = "DecodePCRelLabel19"; | |
2328 | let PrintMethod = "printAlignedLabel"; | |
2329 | let ParserMatchClass = PCRelLabel19Operand; | |
2330 | } | |
2331 | ||
2332 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
2333 | class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm> | |
2334 | : I<(outs regtype:$Rt), (ins am_ldrlit:$label), | |
2335 | asm, "\t$Rt, $label", "", []>, | |
2336 | Sched<[WriteLD]> { | |
2337 | bits<5> Rt; | |
2338 | bits<19> label; | |
2339 | let Inst{31-30} = opc; | |
2340 | let Inst{29-27} = 0b011; | |
2341 | let Inst{26} = V; | |
2342 | let Inst{25-24} = 0b00; | |
2343 | let Inst{23-5} = label; | |
2344 | let Inst{4-0} = Rt; | |
2345 | } | |
2346 | ||
2347 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in | |
2348 | class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat> | |
2349 | : I<(outs), (ins prfop:$Rt, am_ldrlit:$label), | |
2350 | asm, "\t$Rt, $label", "", pat>, | |
2351 | Sched<[WriteLD]> { | |
2352 | bits<5> Rt; | |
2353 | bits<19> label; | |
2354 | let Inst{31-30} = opc; | |
2355 | let Inst{29-27} = 0b011; | |
2356 | let Inst{26} = V; | |
2357 | let Inst{25-24} = 0b00; | |
2358 | let Inst{23-5} = label; | |
2359 | let Inst{4-0} = Rt; | |
2360 | } | |
2361 | ||
2362 | //--- | |
2363 | // Load/store register offset | |
2364 | //--- | |
2365 | ||
2366 | def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>; | |
2367 | def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>; | |
2368 | def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>; | |
2369 | def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>; | |
2370 | def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>; | |
2371 | ||
2372 | def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>; | |
2373 | def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>; | |
2374 | def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>; | |
2375 | def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>; | |
2376 | def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>; | |
2377 | ||
2378 | class MemExtendOperand<string Reg, int Width> : AsmOperandClass { | |
2379 | let Name = "Mem" # Reg # "Extend" # Width; | |
2380 | let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">"; | |
2381 | let RenderMethod = "addMemExtendOperands"; | |
2382 | let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width; | |
2383 | } | |
2384 | ||
2385 | def MemWExtend8Operand : MemExtendOperand<"W", 8> { | |
2386 | // The address "[x0, x1, lsl #0]" actually maps to the variant which performs | |
2387 | // the trivial shift. | |
2388 | let RenderMethod = "addMemExtend8Operands"; | |
2389 | } | |
2390 | def MemWExtend16Operand : MemExtendOperand<"W", 16>; | |
2391 | def MemWExtend32Operand : MemExtendOperand<"W", 32>; | |
2392 | def MemWExtend64Operand : MemExtendOperand<"W", 64>; | |
2393 | def MemWExtend128Operand : MemExtendOperand<"W", 128>; | |
2394 | ||
2395 | def MemXExtend8Operand : MemExtendOperand<"X", 8> { | |
2396 | // The address "[x0, x1, lsl #0]" actually maps to the variant which performs | |
2397 | // the trivial shift. | |
2398 | let RenderMethod = "addMemExtend8Operands"; | |
2399 | } | |
2400 | def MemXExtend16Operand : MemExtendOperand<"X", 16>; | |
2401 | def MemXExtend32Operand : MemExtendOperand<"X", 32>; | |
2402 | def MemXExtend64Operand : MemExtendOperand<"X", 64>; | |
2403 | def MemXExtend128Operand : MemExtendOperand<"X", 128>; | |
2404 | ||
2405 | class ro_extend<AsmOperandClass ParserClass, string Reg, int Width> | |
2406 | : Operand<i32> { | |
2407 | let ParserMatchClass = ParserClass; | |
2408 | let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">"; | |
2409 | let DecoderMethod = "DecodeMemExtend"; | |
2410 | let EncoderMethod = "getMemExtendOpValue"; | |
2411 | let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift); | |
2412 | } | |
2413 | ||
2414 | def ro_Wextend8 : ro_extend<MemWExtend8Operand, "w", 8>; | |
2415 | def ro_Wextend16 : ro_extend<MemWExtend16Operand, "w", 16>; | |
2416 | def ro_Wextend32 : ro_extend<MemWExtend32Operand, "w", 32>; | |
2417 | def ro_Wextend64 : ro_extend<MemWExtend64Operand, "w", 64>; | |
2418 | def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>; | |
2419 | ||
2420 | def ro_Xextend8 : ro_extend<MemXExtend8Operand, "x", 8>; | |
2421 | def ro_Xextend16 : ro_extend<MemXExtend16Operand, "x", 16>; | |
2422 | def ro_Xextend32 : ro_extend<MemXExtend32Operand, "x", 32>; | |
2423 | def ro_Xextend64 : ro_extend<MemXExtend64Operand, "x", 64>; | |
2424 | def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>; | |
2425 | ||
2426 | class ROAddrMode<ComplexPattern windex, ComplexPattern xindex, | |
2427 | Operand wextend, Operand xextend> { | |
2428 | // CodeGen-level pattern covering the entire addressing mode. | |
2429 | ComplexPattern Wpat = windex; | |
2430 | ComplexPattern Xpat = xindex; | |
2431 | ||
2432 | // Asm-level Operand covering the valid "uxtw #3" style syntax. | |
2433 | Operand Wext = wextend; | |
2434 | Operand Xext = xextend; | |
2435 | } | |
2436 | ||
2437 | def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>; | |
2438 | def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>; | |
2439 | def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>; | |
2440 | def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>; | |
2441 | def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128, | |
2442 | ro_Xextend128>; | |
2443 | ||
2444 | class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2445 | string asm, dag ins, dag outs, list<dag> pat> | |
2446 | : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> { | |
2447 | bits<5> Rt; | |
2448 | bits<5> Rn; | |
2449 | bits<5> Rm; | |
2450 | bits<2> extend; | |
2451 | let Inst{31-30} = sz; | |
2452 | let Inst{29-27} = 0b111; | |
2453 | let Inst{26} = V; | |
2454 | let Inst{25-24} = 0b00; | |
2455 | let Inst{23-22} = opc; | |
2456 | let Inst{21} = 1; | |
2457 | let Inst{20-16} = Rm; | |
2458 | let Inst{15} = extend{1}; // sign extend Rm? | |
2459 | let Inst{14} = 1; | |
2460 | let Inst{12} = extend{0}; // do shift? | |
2461 | let Inst{11-10} = 0b10; | |
2462 | let Inst{9-5} = Rn; | |
2463 | let Inst{4-0} = Rt; | |
2464 | } | |
2465 | ||
2466 | class ROInstAlias<string asm, RegisterClass regtype, Instruction INST> | |
2467 | : InstAlias<asm # " $Rt, [$Rn, $Rm]", | |
2468 | (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>; | |
2469 | ||
2470 | multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2471 | string asm, ValueType Ty, SDPatternOperator loadop> { | |
2472 | let AddedComplexity = 10 in | |
2473 | def roW : LoadStore8RO<sz, V, opc, regtype, asm, | |
2474 | (outs regtype:$Rt), | |
2475 | (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend), | |
2476 | [(set (Ty regtype:$Rt), | |
2477 | (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, | |
2478 | ro_Wextend8:$extend)))]>, | |
2479 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2480 | let Inst{13} = 0b0; | |
2481 | } | |
2482 | ||
2483 | let AddedComplexity = 10 in | |
2484 | def roX : LoadStore8RO<sz, V, opc, regtype, asm, | |
2485 | (outs regtype:$Rt), | |
2486 | (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend), | |
2487 | [(set (Ty regtype:$Rt), | |
2488 | (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, | |
2489 | ro_Xextend8:$extend)))]>, | |
2490 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2491 | let Inst{13} = 0b1; | |
2492 | } | |
2493 | ||
2494 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2495 | } | |
2496 | ||
2497 | multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2498 | string asm, ValueType Ty, SDPatternOperator storeop> { | |
2499 | let AddedComplexity = 10 in | |
2500 | def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs), | |
2501 | (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend), | |
2502 | [(storeop (Ty regtype:$Rt), | |
2503 | (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, | |
2504 | ro_Wextend8:$extend))]>, | |
2505 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2506 | let Inst{13} = 0b0; | |
2507 | } | |
2508 | ||
2509 | let AddedComplexity = 10 in | |
2510 | def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs), | |
2511 | (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend), | |
2512 | [(storeop (Ty regtype:$Rt), | |
2513 | (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, | |
2514 | ro_Xextend8:$extend))]>, | |
2515 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2516 | let Inst{13} = 0b1; | |
2517 | } | |
2518 | ||
2519 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2520 | } | |
2521 | ||
2522 | class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2523 | string asm, dag ins, dag outs, list<dag> pat> | |
2524 | : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> { | |
2525 | bits<5> Rt; | |
2526 | bits<5> Rn; | |
2527 | bits<5> Rm; | |
2528 | bits<2> extend; | |
2529 | let Inst{31-30} = sz; | |
2530 | let Inst{29-27} = 0b111; | |
2531 | let Inst{26} = V; | |
2532 | let Inst{25-24} = 0b00; | |
2533 | let Inst{23-22} = opc; | |
2534 | let Inst{21} = 1; | |
2535 | let Inst{20-16} = Rm; | |
2536 | let Inst{15} = extend{1}; // sign extend Rm? | |
2537 | let Inst{14} = 1; | |
2538 | let Inst{12} = extend{0}; // do shift? | |
2539 | let Inst{11-10} = 0b10; | |
2540 | let Inst{9-5} = Rn; | |
2541 | let Inst{4-0} = Rt; | |
2542 | } | |
2543 | ||
2544 | multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2545 | string asm, ValueType Ty, SDPatternOperator loadop> { | |
2546 | let AddedComplexity = 10 in | |
2547 | def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2548 | (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend), | |
2549 | [(set (Ty regtype:$Rt), | |
2550 | (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, | |
2551 | ro_Wextend16:$extend)))]>, | |
2552 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2553 | let Inst{13} = 0b0; | |
2554 | } | |
2555 | ||
2556 | let AddedComplexity = 10 in | |
2557 | def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2558 | (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend), | |
2559 | [(set (Ty regtype:$Rt), | |
2560 | (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm, | |
2561 | ro_Xextend16:$extend)))]>, | |
2562 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2563 | let Inst{13} = 0b1; | |
2564 | } | |
2565 | ||
2566 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2567 | } | |
2568 | ||
2569 | multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2570 | string asm, ValueType Ty, SDPatternOperator storeop> { | |
2571 | let AddedComplexity = 10 in | |
2572 | def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs), | |
2573 | (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend), | |
2574 | [(storeop (Ty regtype:$Rt), | |
2575 | (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, | |
2576 | ro_Wextend16:$extend))]>, | |
2577 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2578 | let Inst{13} = 0b0; | |
2579 | } | |
2580 | ||
2581 | let AddedComplexity = 10 in | |
2582 | def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs), | |
2583 | (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend), | |
2584 | [(storeop (Ty regtype:$Rt), | |
2585 | (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm, | |
2586 | ro_Xextend16:$extend))]>, | |
2587 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2588 | let Inst{13} = 0b1; | |
2589 | } | |
2590 | ||
2591 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2592 | } | |
2593 | ||
2594 | class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2595 | string asm, dag ins, dag outs, list<dag> pat> | |
2596 | : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> { | |
2597 | bits<5> Rt; | |
2598 | bits<5> Rn; | |
2599 | bits<5> Rm; | |
2600 | bits<2> extend; | |
2601 | let Inst{31-30} = sz; | |
2602 | let Inst{29-27} = 0b111; | |
2603 | let Inst{26} = V; | |
2604 | let Inst{25-24} = 0b00; | |
2605 | let Inst{23-22} = opc; | |
2606 | let Inst{21} = 1; | |
2607 | let Inst{20-16} = Rm; | |
2608 | let Inst{15} = extend{1}; // sign extend Rm? | |
2609 | let Inst{14} = 1; | |
2610 | let Inst{12} = extend{0}; // do shift? | |
2611 | let Inst{11-10} = 0b10; | |
2612 | let Inst{9-5} = Rn; | |
2613 | let Inst{4-0} = Rt; | |
2614 | } | |
2615 | ||
2616 | multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2617 | string asm, ValueType Ty, SDPatternOperator loadop> { | |
2618 | let AddedComplexity = 10 in | |
2619 | def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2620 | (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend), | |
2621 | [(set (Ty regtype:$Rt), | |
2622 | (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, | |
2623 | ro_Wextend32:$extend)))]>, | |
2624 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2625 | let Inst{13} = 0b0; | |
2626 | } | |
2627 | ||
2628 | let AddedComplexity = 10 in | |
2629 | def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2630 | (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend), | |
2631 | [(set (Ty regtype:$Rt), | |
2632 | (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, | |
2633 | ro_Xextend32:$extend)))]>, | |
2634 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2635 | let Inst{13} = 0b1; | |
2636 | } | |
2637 | ||
2638 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2639 | } | |
2640 | ||
2641 | multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2642 | string asm, ValueType Ty, SDPatternOperator storeop> { | |
2643 | let AddedComplexity = 10 in | |
2644 | def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs), | |
2645 | (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend), | |
2646 | [(storeop (Ty regtype:$Rt), | |
2647 | (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, | |
2648 | ro_Wextend32:$extend))]>, | |
2649 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2650 | let Inst{13} = 0b0; | |
2651 | } | |
2652 | ||
2653 | let AddedComplexity = 10 in | |
2654 | def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs), | |
2655 | (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend), | |
2656 | [(storeop (Ty regtype:$Rt), | |
2657 | (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, | |
2658 | ro_Xextend32:$extend))]>, | |
2659 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2660 | let Inst{13} = 0b1; | |
2661 | } | |
2662 | ||
2663 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2664 | } | |
2665 | ||
2666 | class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2667 | string asm, dag ins, dag outs, list<dag> pat> | |
2668 | : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> { | |
2669 | bits<5> Rt; | |
2670 | bits<5> Rn; | |
2671 | bits<5> Rm; | |
2672 | bits<2> extend; | |
2673 | let Inst{31-30} = sz; | |
2674 | let Inst{29-27} = 0b111; | |
2675 | let Inst{26} = V; | |
2676 | let Inst{25-24} = 0b00; | |
2677 | let Inst{23-22} = opc; | |
2678 | let Inst{21} = 1; | |
2679 | let Inst{20-16} = Rm; | |
2680 | let Inst{15} = extend{1}; // sign extend Rm? | |
2681 | let Inst{14} = 1; | |
2682 | let Inst{12} = extend{0}; // do shift? | |
2683 | let Inst{11-10} = 0b10; | |
2684 | let Inst{9-5} = Rn; | |
2685 | let Inst{4-0} = Rt; | |
2686 | } | |
2687 | ||
2688 | multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2689 | string asm, ValueType Ty, SDPatternOperator loadop> { | |
2690 | let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
2691 | def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2692 | (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend), | |
2693 | [(set (Ty regtype:$Rt), | |
2694 | (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, | |
2695 | ro_Wextend64:$extend)))]>, | |
2696 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2697 | let Inst{13} = 0b0; | |
2698 | } | |
2699 | ||
2700 | let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
2701 | def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2702 | (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend), | |
2703 | [(set (Ty regtype:$Rt), | |
2704 | (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, | |
2705 | ro_Xextend64:$extend)))]>, | |
2706 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2707 | let Inst{13} = 0b1; | |
2708 | } | |
2709 | ||
2710 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2711 | } | |
2712 | ||
2713 | multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2714 | string asm, ValueType Ty, SDPatternOperator storeop> { | |
2715 | let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
2716 | def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs), | |
2717 | (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend), | |
2718 | [(storeop (Ty regtype:$Rt), | |
2719 | (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, | |
2720 | ro_Wextend64:$extend))]>, | |
2721 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2722 | let Inst{13} = 0b0; | |
2723 | } | |
2724 | ||
2725 | let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
2726 | def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs), | |
2727 | (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend), | |
2728 | [(storeop (Ty regtype:$Rt), | |
2729 | (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, | |
2730 | ro_Xextend64:$extend))]>, | |
2731 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2732 | let Inst{13} = 0b1; | |
2733 | } | |
2734 | ||
2735 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2736 | } | |
2737 | ||
2738 | class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2739 | string asm, dag ins, dag outs, list<dag> pat> | |
2740 | : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> { | |
2741 | bits<5> Rt; | |
2742 | bits<5> Rn; | |
2743 | bits<5> Rm; | |
2744 | bits<2> extend; | |
2745 | let Inst{31-30} = sz; | |
2746 | let Inst{29-27} = 0b111; | |
2747 | let Inst{26} = V; | |
2748 | let Inst{25-24} = 0b00; | |
2749 | let Inst{23-22} = opc; | |
2750 | let Inst{21} = 1; | |
2751 | let Inst{20-16} = Rm; | |
2752 | let Inst{15} = extend{1}; // sign extend Rm? | |
2753 | let Inst{14} = 1; | |
2754 | let Inst{12} = extend{0}; // do shift? | |
2755 | let Inst{11-10} = 0b10; | |
2756 | let Inst{9-5} = Rn; | |
2757 | let Inst{4-0} = Rt; | |
2758 | } | |
2759 | ||
2760 | multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2761 | string asm, ValueType Ty, SDPatternOperator loadop> { | |
2762 | let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
2763 | def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2764 | (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend), | |
2765 | [(set (Ty regtype:$Rt), | |
2766 | (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm, | |
2767 | ro_Wextend128:$extend)))]>, | |
2768 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2769 | let Inst{13} = 0b0; | |
2770 | } | |
2771 | ||
2772 | let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
2773 | def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt), | |
2774 | (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend), | |
2775 | [(set (Ty regtype:$Rt), | |
2776 | (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm, | |
2777 | ro_Xextend128:$extend)))]>, | |
2778 | Sched<[WriteLDIdx, ReadAdrBase]> { | |
2779 | let Inst{13} = 0b1; | |
2780 | } | |
2781 | ||
2782 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2783 | } | |
2784 | ||
2785 | multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2786 | string asm, ValueType Ty, SDPatternOperator storeop> { | |
2787 | let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
2788 | def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs), | |
2789 | (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend), | |
2790 | [(storeop (Ty regtype:$Rt), | |
2791 | (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm, | |
2792 | ro_Wextend128:$extend))]>, | |
2793 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2794 | let Inst{13} = 0b0; | |
2795 | } | |
2796 | ||
2797 | let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
2798 | def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs), | |
2799 | (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend), | |
2800 | [(storeop (Ty regtype:$Rt), | |
2801 | (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm, | |
2802 | ro_Xextend128:$extend))]>, | |
2803 | Sched<[WriteSTIdx, ReadAdrBase]> { | |
2804 | let Inst{13} = 0b1; | |
2805 | } | |
2806 | ||
2807 | def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>; | |
2808 | } | |
2809 | ||
2810 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in | |
2811 | class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins, | |
2812 | string asm, list<dag> pat> | |
2813 | : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>, | |
2814 | Sched<[WriteLD]> { | |
2815 | bits<5> Rt; | |
2816 | bits<5> Rn; | |
2817 | bits<5> Rm; | |
2818 | bits<2> extend; | |
2819 | let Inst{31-30} = sz; | |
2820 | let Inst{29-27} = 0b111; | |
2821 | let Inst{26} = V; | |
2822 | let Inst{25-24} = 0b00; | |
2823 | let Inst{23-22} = opc; | |
2824 | let Inst{21} = 1; | |
2825 | let Inst{20-16} = Rm; | |
2826 | let Inst{15} = extend{1}; // sign extend Rm? | |
2827 | let Inst{14} = 1; | |
2828 | let Inst{12} = extend{0}; // do shift? | |
2829 | let Inst{11-10} = 0b10; | |
2830 | let Inst{9-5} = Rn; | |
2831 | let Inst{4-0} = Rt; | |
2832 | } | |
2833 | ||
2834 | multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> { | |
2835 | def roW : BasePrefetchRO<sz, V, opc, (outs), | |
2836 | (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend), | |
2837 | asm, [(AArch64Prefetch imm:$Rt, | |
2838 | (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, | |
2839 | ro_Wextend64:$extend))]> { | |
2840 | let Inst{13} = 0b0; | |
2841 | } | |
2842 | ||
2843 | def roX : BasePrefetchRO<sz, V, opc, (outs), | |
2844 | (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend), | |
2845 | asm, [(AArch64Prefetch imm:$Rt, | |
2846 | (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, | |
2847 | ro_Xextend64:$extend))]> { | |
2848 | let Inst{13} = 0b1; | |
2849 | } | |
2850 | ||
2851 | def : InstAlias<"prfm $Rt, [$Rn, $Rm]", | |
2852 | (!cast<Instruction>(NAME # "roX") prfop:$Rt, | |
2853 | GPR64sp:$Rn, GPR64:$Rm, 0, 0)>; | |
2854 | } | |
2855 | ||
2856 | //--- | |
2857 | // Load/store unscaled immediate | |
2858 | //--- | |
2859 | ||
2860 | def am_unscaled8 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>; | |
2861 | def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>; | |
2862 | def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>; | |
2863 | def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>; | |
2864 | def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>; | |
2865 | ||
2866 | class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, | |
2867 | string asm, list<dag> pattern> | |
2868 | : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> { | |
2869 | bits<5> Rt; | |
2870 | bits<5> Rn; | |
2871 | bits<9> offset; | |
2872 | let Inst{31-30} = sz; | |
2873 | let Inst{29-27} = 0b111; | |
2874 | let Inst{26} = V; | |
2875 | let Inst{25-24} = 0b00; | |
2876 | let Inst{23-22} = opc; | |
2877 | let Inst{21} = 0; | |
2878 | let Inst{20-12} = offset; | |
2879 | let Inst{11-10} = 0b00; | |
2880 | let Inst{9-5} = Rn; | |
2881 | let Inst{4-0} = Rt; | |
2882 | ||
2883 | let DecoderMethod = "DecodeSignedLdStInstruction"; | |
2884 | } | |
2885 | ||
2886 | multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2887 | string asm, list<dag> pattern> { | |
2888 | let AddedComplexity = 1 in // try this before LoadUI | |
2889 | def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt), | |
2890 | (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>, | |
2891 | Sched<[WriteLD]>; | |
2892 | ||
2893 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2894 | (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; | |
2895 | } | |
2896 | ||
2897 | multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2898 | string asm, list<dag> pattern> { | |
2899 | let AddedComplexity = 1 in // try this before StoreUI | |
2900 | def i : BaseLoadStoreUnscale<sz, V, opc, (outs), | |
2901 | (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), | |
2902 | asm, pattern>, | |
2903 | Sched<[WriteST]>; | |
2904 | ||
2905 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2906 | (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; | |
2907 | } | |
2908 | ||
2909 | multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, | |
2910 | list<dag> pat> { | |
2911 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in | |
2912 | def i : BaseLoadStoreUnscale<sz, V, opc, (outs), | |
2913 | (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset), | |
2914 | asm, pat>, | |
2915 | Sched<[WriteLD]>; | |
2916 | ||
2917 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2918 | (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>; | |
2919 | } | |
2920 | ||
2921 | //--- | |
2922 | // Load/store unscaled immediate, unprivileged | |
2923 | //--- | |
2924 | ||
2925 | class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc, | |
2926 | dag oops, dag iops, string asm> | |
2927 | : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> { | |
2928 | bits<5> Rt; | |
2929 | bits<5> Rn; | |
2930 | bits<9> offset; | |
2931 | let Inst{31-30} = sz; | |
2932 | let Inst{29-27} = 0b111; | |
2933 | let Inst{26} = V; | |
2934 | let Inst{25-24} = 0b00; | |
2935 | let Inst{23-22} = opc; | |
2936 | let Inst{21} = 0; | |
2937 | let Inst{20-12} = offset; | |
2938 | let Inst{11-10} = 0b10; | |
2939 | let Inst{9-5} = Rn; | |
2940 | let Inst{4-0} = Rt; | |
2941 | ||
2942 | let DecoderMethod = "DecodeSignedLdStInstruction"; | |
2943 | } | |
2944 | ||
2945 | multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, | |
2946 | RegisterClass regtype, string asm> { | |
2947 | let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in | |
2948 | def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt), | |
2949 | (ins GPR64sp:$Rn, simm9:$offset), asm>, | |
2950 | Sched<[WriteLD]>; | |
2951 | ||
2952 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2953 | (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; | |
2954 | } | |
2955 | ||
2956 | multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, | |
2957 | RegisterClass regtype, string asm> { | |
2958 | let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in | |
2959 | def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs), | |
2960 | (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), | |
2961 | asm>, | |
2962 | Sched<[WriteST]>; | |
2963 | ||
2964 | def : InstAlias<asm # " $Rt, [$Rn]", | |
2965 | (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; | |
2966 | } | |
2967 | ||
2968 | //--- | |
2969 | // Load/store pre-indexed | |
2970 | //--- | |
2971 | ||
2972 | class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, | |
2973 | string asm, string cstr, list<dag> pat> | |
2974 | : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> { | |
2975 | bits<5> Rt; | |
2976 | bits<5> Rn; | |
2977 | bits<9> offset; | |
2978 | let Inst{31-30} = sz; | |
2979 | let Inst{29-27} = 0b111; | |
2980 | let Inst{26} = V; | |
2981 | let Inst{25-24} = 0; | |
2982 | let Inst{23-22} = opc; | |
2983 | let Inst{21} = 0; | |
2984 | let Inst{20-12} = offset; | |
2985 | let Inst{11-10} = 0b11; | |
2986 | let Inst{9-5} = Rn; | |
2987 | let Inst{4-0} = Rt; | |
2988 | ||
2989 | let DecoderMethod = "DecodeSignedLdStInstruction"; | |
2990 | } | |
2991 | ||
2992 | let hasSideEffects = 0 in { | |
2993 | let mayStore = 0, mayLoad = 1 in | |
2994 | class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
2995 | string asm> | |
2996 | : BaseLoadStorePreIdx<sz, V, opc, | |
2997 | (outs GPR64sp:$wback, regtype:$Rt), | |
2998 | (ins GPR64sp:$Rn, simm9:$offset), asm, | |
2999 | "$Rn = $wback,@earlyclobber $wback", []>, | |
3000 | Sched<[WriteLD, WriteAdr]>; | |
3001 | ||
3002 | let mayStore = 1, mayLoad = 0 in | |
3003 | class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
3004 | string asm, SDPatternOperator storeop, ValueType Ty> | |
3005 | : BaseLoadStorePreIdx<sz, V, opc, | |
3006 | (outs GPR64sp:$wback), | |
3007 | (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), | |
3008 | asm, "$Rn = $wback,@earlyclobber $wback", | |
3009 | [(set GPR64sp:$wback, | |
3010 | (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>, | |
3011 | Sched<[WriteAdr, WriteST]>; | |
3012 | } // hasSideEffects = 0 | |
3013 | ||
3014 | //--- | |
3015 | // Load/store post-indexed | |
3016 | //--- | |
3017 | ||
3018 | class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, | |
3019 | string asm, string cstr, list<dag> pat> | |
3020 | : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> { | |
3021 | bits<5> Rt; | |
3022 | bits<5> Rn; | |
3023 | bits<9> offset; | |
3024 | let Inst{31-30} = sz; | |
3025 | let Inst{29-27} = 0b111; | |
3026 | let Inst{26} = V; | |
3027 | let Inst{25-24} = 0b00; | |
3028 | let Inst{23-22} = opc; | |
3029 | let Inst{21} = 0b0; | |
3030 | let Inst{20-12} = offset; | |
3031 | let Inst{11-10} = 0b01; | |
3032 | let Inst{9-5} = Rn; | |
3033 | let Inst{4-0} = Rt; | |
3034 | ||
3035 | let DecoderMethod = "DecodeSignedLdStInstruction"; | |
3036 | } | |
3037 | ||
3038 | let hasSideEffects = 0 in { | |
3039 | let mayStore = 0, mayLoad = 1 in | |
3040 | class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
3041 | string asm> | |
3042 | : BaseLoadStorePostIdx<sz, V, opc, | |
3043 | (outs GPR64sp:$wback, regtype:$Rt), | |
3044 | (ins GPR64sp:$Rn, simm9:$offset), | |
3045 | asm, "$Rn = $wback,@earlyclobber $wback", []>, | |
3046 | Sched<[WriteLD, WriteI]>; | |
3047 | ||
3048 | let mayStore = 1, mayLoad = 0 in | |
3049 | class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, | |
3050 | string asm, SDPatternOperator storeop, ValueType Ty> | |
3051 | : BaseLoadStorePostIdx<sz, V, opc, | |
3052 | (outs GPR64sp:$wback), | |
3053 | (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), | |
3054 | asm, "$Rn = $wback,@earlyclobber $wback", | |
3055 | [(set GPR64sp:$wback, | |
3056 | (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>, | |
3057 | Sched<[WriteAdr, WriteST, ReadAdrBase]>; | |
3058 | } // hasSideEffects = 0 | |
3059 | ||
3060 | ||
3061 | //--- | |
3062 | // Load/store pair | |
3063 | //--- | |
3064 | ||
3065 | // (indexed, offset) | |
3066 | ||
3067 | class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops, | |
3068 | string asm> | |
3069 | : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> { | |
3070 | bits<5> Rt; | |
3071 | bits<5> Rt2; | |
3072 | bits<5> Rn; | |
3073 | bits<7> offset; | |
3074 | let Inst{31-30} = opc; | |
3075 | let Inst{29-27} = 0b101; | |
3076 | let Inst{26} = V; | |
3077 | let Inst{25-23} = 0b010; | |
3078 | let Inst{22} = L; | |
3079 | let Inst{21-15} = offset; | |
3080 | let Inst{14-10} = Rt2; | |
3081 | let Inst{9-5} = Rn; | |
3082 | let Inst{4-0} = Rt; | |
3083 | ||
3084 | let DecoderMethod = "DecodePairLdStInstruction"; | |
3085 | } | |
3086 | ||
3087 | multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype, | |
3088 | Operand indextype, string asm> { | |
3089 | let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in | |
3090 | def i : BaseLoadStorePairOffset<opc, V, 1, | |
3091 | (outs regtype:$Rt, regtype:$Rt2), | |
3092 | (ins GPR64sp:$Rn, indextype:$offset), asm>, | |
3093 | Sched<[WriteLD, WriteLDHi]>; | |
3094 | ||
3095 | def : InstAlias<asm # " $Rt, $Rt2, [$Rn]", | |
3096 | (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2, | |
3097 | GPR64sp:$Rn, 0)>; | |
3098 | } | |
3099 | ||
3100 | ||
3101 | multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype, | |
3102 | Operand indextype, string asm> { | |
3103 | let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in | |
3104 | def i : BaseLoadStorePairOffset<opc, V, 0, (outs), | |
3105 | (ins regtype:$Rt, regtype:$Rt2, | |
3106 | GPR64sp:$Rn, indextype:$offset), | |
3107 | asm>, | |
3108 | Sched<[WriteSTP]>; | |
3109 | ||
3110 | def : InstAlias<asm # " $Rt, $Rt2, [$Rn]", | |
3111 | (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2, | |
3112 | GPR64sp:$Rn, 0)>; | |
3113 | } | |
3114 | ||
3115 | // (pre-indexed) | |
3116 | class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops, | |
3117 | string asm> | |
3118 | : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> { | |
3119 | bits<5> Rt; | |
3120 | bits<5> Rt2; | |
3121 | bits<5> Rn; | |
3122 | bits<7> offset; | |
3123 | let Inst{31-30} = opc; | |
3124 | let Inst{29-27} = 0b101; | |
3125 | let Inst{26} = V; | |
3126 | let Inst{25-23} = 0b011; | |
3127 | let Inst{22} = L; | |
3128 | let Inst{21-15} = offset; | |
3129 | let Inst{14-10} = Rt2; | |
3130 | let Inst{9-5} = Rn; | |
3131 | let Inst{4-0} = Rt; | |
3132 | ||
3133 | let DecoderMethod = "DecodePairLdStInstruction"; | |
3134 | } | |
3135 | ||
3136 | let hasSideEffects = 0 in { | |
3137 | let mayStore = 0, mayLoad = 1 in | |
3138 | class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype, | |
3139 | Operand indextype, string asm> | |
3140 | : BaseLoadStorePairPreIdx<opc, V, 1, | |
3141 | (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2), | |
3142 | (ins GPR64sp:$Rn, indextype:$offset), asm>, | |
3143 | Sched<[WriteLD, WriteLDHi, WriteAdr]>; | |
3144 | ||
3145 | let mayStore = 1, mayLoad = 0 in | |
3146 | class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype, | |
3147 | Operand indextype, string asm> | |
3148 | : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback), | |
3149 | (ins regtype:$Rt, regtype:$Rt2, | |
3150 | GPR64sp:$Rn, indextype:$offset), | |
3151 | asm>, | |
3152 | Sched<[WriteAdr, WriteSTP]>; | |
3153 | } // hasSideEffects = 0 | |
3154 | ||
3155 | // (post-indexed) | |
3156 | ||
3157 | class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops, | |
3158 | string asm> | |
3159 | : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> { | |
3160 | bits<5> Rt; | |
3161 | bits<5> Rt2; | |
3162 | bits<5> Rn; | |
3163 | bits<7> offset; | |
3164 | let Inst{31-30} = opc; | |
3165 | let Inst{29-27} = 0b101; | |
3166 | let Inst{26} = V; | |
3167 | let Inst{25-23} = 0b001; | |
3168 | let Inst{22} = L; | |
3169 | let Inst{21-15} = offset; | |
3170 | let Inst{14-10} = Rt2; | |
3171 | let Inst{9-5} = Rn; | |
3172 | let Inst{4-0} = Rt; | |
3173 | ||
3174 | let DecoderMethod = "DecodePairLdStInstruction"; | |
3175 | } | |
3176 | ||
3177 | let hasSideEffects = 0 in { | |
3178 | let mayStore = 0, mayLoad = 1 in | |
3179 | class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype, | |
3180 | Operand idxtype, string asm> | |
3181 | : BaseLoadStorePairPostIdx<opc, V, 1, | |
3182 | (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2), | |
3183 | (ins GPR64sp:$Rn, idxtype:$offset), asm>, | |
3184 | Sched<[WriteLD, WriteLDHi, WriteAdr]>; | |
3185 | ||
3186 | let mayStore = 1, mayLoad = 0 in | |
3187 | class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype, | |
3188 | Operand idxtype, string asm> | |
3189 | : BaseLoadStorePairPostIdx<opc, V, 0, (outs), | |
3190 | (ins GPR64sp:$wback, regtype:$Rt, regtype:$Rt2, | |
3191 | GPR64sp:$Rn, idxtype:$offset), | |
3192 | asm>, | |
3193 | Sched<[WriteAdr, WriteSTP]>; | |
3194 | } // hasSideEffects = 0 | |
3195 | ||
3196 | // (no-allocate) | |
3197 | ||
3198 | class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops, | |
3199 | string asm> | |
3200 | : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> { | |
3201 | bits<5> Rt; | |
3202 | bits<5> Rt2; | |
3203 | bits<5> Rn; | |
3204 | bits<7> offset; | |
3205 | let Inst{31-30} = opc; | |
3206 | let Inst{29-27} = 0b101; | |
3207 | let Inst{26} = V; | |
3208 | let Inst{25-23} = 0b000; | |
3209 | let Inst{22} = L; | |
3210 | let Inst{21-15} = offset; | |
3211 | let Inst{14-10} = Rt2; | |
3212 | let Inst{9-5} = Rn; | |
3213 | let Inst{4-0} = Rt; | |
3214 | ||
3215 | let DecoderMethod = "DecodePairLdStInstruction"; | |
3216 | } | |
3217 | ||
3218 | multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype, | |
3219 | Operand indextype, string asm> { | |
3220 | let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in | |
3221 | def i : BaseLoadStorePairNoAlloc<opc, V, 1, | |
3222 | (outs regtype:$Rt, regtype:$Rt2), | |
3223 | (ins GPR64sp:$Rn, indextype:$offset), asm>, | |
3224 | Sched<[WriteLD, WriteLDHi]>; | |
3225 | ||
3226 | ||
3227 | def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]", | |
3228 | (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2, | |
3229 | GPR64sp:$Rn, 0)>; | |
3230 | } | |
3231 | ||
3232 | multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype, | |
3233 | Operand indextype, string asm> { | |
3234 | let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in | |
3235 | def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs), | |
3236 | (ins regtype:$Rt, regtype:$Rt2, | |
3237 | GPR64sp:$Rn, indextype:$offset), | |
3238 | asm>, | |
3239 | Sched<[WriteSTP]>; | |
3240 | ||
3241 | def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]", | |
3242 | (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2, | |
3243 | GPR64sp:$Rn, 0)>; | |
3244 | } | |
3245 | ||
3246 | //--- | |
3247 | // Load/store exclusive | |
3248 | //--- | |
3249 | ||
3250 | // True exclusive operations write to and/or read from the system's exclusive | |
3251 | // monitors, which as far as a compiler is concerned can be modelled as a | |
3252 | // random shared memory address. Hence LoadExclusive mayStore. | |
3253 | // | |
3254 | // Since these instructions have the undefined register bits set to 1 in | |
3255 | // their canonical form, we need a post encoder method to set those bits | |
3256 | // to 1 when encoding these instructions. We do this using the | |
3257 | // fixLoadStoreExclusive function. This function has template parameters: | |
3258 | // | |
3259 | // fixLoadStoreExclusive<int hasRs, int hasRt2> | |
3260 | // | |
3261 | // hasRs indicates that the instruction uses the Rs field, so we won't set | |
3262 | // it to 1 (and the same for Rt2). We don't need template parameters for | |
3263 | // the other register fields since Rt and Rn are always used. | |
3264 | // | |
3265 | let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in | |
3266 | class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3267 | dag oops, dag iops, string asm, string operands> | |
3268 | : I<oops, iops, asm, operands, "", []> { | |
3269 | let Inst{31-30} = sz; | |
3270 | let Inst{29-24} = 0b001000; | |
3271 | let Inst{23} = o2; | |
3272 | let Inst{22} = L; | |
3273 | let Inst{21} = o1; | |
3274 | let Inst{15} = o0; | |
3275 | ||
3276 | let DecoderMethod = "DecodeExclusiveLdStInstruction"; | |
3277 | } | |
3278 | ||
3279 | // Neither Rs nor Rt2 operands. | |
3280 | class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3281 | dag oops, dag iops, string asm, string operands> | |
3282 | : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> { | |
3283 | bits<5> Rt; | |
3284 | bits<5> Rn; | |
3285 | let Inst{9-5} = Rn; | |
3286 | let Inst{4-0} = Rt; | |
3287 | ||
3288 | let PostEncoderMethod = "fixLoadStoreExclusive<0,0>"; | |
3289 | } | |
3290 | ||
3291 | // Simple load acquires don't set the exclusive monitor | |
3292 | let mayLoad = 1, mayStore = 0 in | |
3293 | class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3294 | RegisterClass regtype, string asm> | |
3295 | : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt), | |
3296 | (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">, | |
3297 | Sched<[WriteLD]>; | |
3298 | ||
3299 | class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3300 | RegisterClass regtype, string asm> | |
3301 | : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt), | |
3302 | (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">, | |
3303 | Sched<[WriteLD]>; | |
3304 | ||
3305 | class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3306 | RegisterClass regtype, string asm> | |
3307 | : BaseLoadStoreExclusive<sz, o2, L, o1, o0, | |
3308 | (outs regtype:$Rt, regtype:$Rt2), | |
3309 | (ins GPR64sp0:$Rn), asm, | |
3310 | "\t$Rt, $Rt2, [$Rn]">, | |
3311 | Sched<[WriteLD, WriteLDHi]> { | |
3312 | bits<5> Rt; | |
3313 | bits<5> Rt2; | |
3314 | bits<5> Rn; | |
3315 | let Inst{14-10} = Rt2; | |
3316 | let Inst{9-5} = Rn; | |
3317 | let Inst{4-0} = Rt; | |
3318 | ||
3319 | let PostEncoderMethod = "fixLoadStoreExclusive<0,1>"; | |
3320 | } | |
3321 | ||
3322 | // Simple store release operations do not check the exclusive monitor. | |
3323 | let mayLoad = 0, mayStore = 1 in | |
3324 | class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3325 | RegisterClass regtype, string asm> | |
3326 | : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs), | |
3327 | (ins regtype:$Rt, GPR64sp0:$Rn), | |
3328 | asm, "\t$Rt, [$Rn]">, | |
3329 | Sched<[WriteST]>; | |
3330 | ||
3331 | let mayLoad = 1, mayStore = 1 in | |
3332 | class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3333 | RegisterClass regtype, string asm> | |
3334 | : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws), | |
3335 | (ins regtype:$Rt, GPR64sp0:$Rn), | |
3336 | asm, "\t$Ws, $Rt, [$Rn]">, | |
3337 | Sched<[WriteSTX]> { | |
3338 | bits<5> Ws; | |
3339 | bits<5> Rt; | |
3340 | bits<5> Rn; | |
3341 | let Inst{20-16} = Ws; | |
3342 | let Inst{9-5} = Rn; | |
3343 | let Inst{4-0} = Rt; | |
3344 | ||
3345 | let Constraints = "@earlyclobber $Ws"; | |
3346 | let PostEncoderMethod = "fixLoadStoreExclusive<1,0>"; | |
3347 | } | |
3348 | ||
3349 | class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0, | |
3350 | RegisterClass regtype, string asm> | |
3351 | : BaseLoadStoreExclusive<sz, o2, L, o1, o0, | |
3352 | (outs GPR32:$Ws), | |
3353 | (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn), | |
3354 | asm, "\t$Ws, $Rt, $Rt2, [$Rn]">, | |
3355 | Sched<[WriteSTX]> { | |
3356 | bits<5> Ws; | |
3357 | bits<5> Rt; | |
3358 | bits<5> Rt2; | |
3359 | bits<5> Rn; | |
3360 | let Inst{20-16} = Ws; | |
3361 | let Inst{14-10} = Rt2; | |
3362 | let Inst{9-5} = Rn; | |
3363 | let Inst{4-0} = Rt; | |
3364 | ||
3365 | let Constraints = "@earlyclobber $Ws"; | |
3366 | } | |
3367 | ||
3368 | //--- | |
3369 | // Exception generation | |
3370 | //--- | |
3371 | ||
3372 | let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in | |
3373 | class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm> | |
3374 | : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>, | |
3375 | Sched<[WriteSys]> { | |
3376 | bits<16> imm; | |
3377 | let Inst{31-24} = 0b11010100; | |
3378 | let Inst{23-21} = op1; | |
3379 | let Inst{20-5} = imm; | |
3380 | let Inst{4-2} = 0b000; | |
3381 | let Inst{1-0} = ll; | |
3382 | } | |
3383 | ||
3384 | let Predicates = [HasFPARMv8] in { | |
3385 | ||
3386 | //--- | |
3387 | // Floating point to integer conversion | |
3388 | //--- | |
3389 | ||
3390 | class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode, | |
3391 | RegisterClass srcType, RegisterClass dstType, | |
3392 | string asm, list<dag> pattern> | |
3393 | : I<(outs dstType:$Rd), (ins srcType:$Rn), | |
3394 | asm, "\t$Rd, $Rn", "", pattern>, | |
3395 | Sched<[WriteFCvt]> { | |
3396 | bits<5> Rd; | |
3397 | bits<5> Rn; | |
3398 | let Inst{30-29} = 0b00; | |
3399 | let Inst{28-24} = 0b11110; | |
3400 | let Inst{23-22} = type; | |
3401 | let Inst{21} = 1; | |
3402 | let Inst{20-19} = rmode; | |
3403 | let Inst{18-16} = opcode; | |
3404 | let Inst{15-10} = 0; | |
3405 | let Inst{9-5} = Rn; | |
3406 | let Inst{4-0} = Rd; | |
3407 | } | |
3408 | ||
3409 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3410 | class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode, | |
3411 | RegisterClass srcType, RegisterClass dstType, | |
3412 | Operand immType, string asm, list<dag> pattern> | |
3413 | : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale), | |
3414 | asm, "\t$Rd, $Rn, $scale", "", pattern>, | |
3415 | Sched<[WriteFCvt]> { | |
3416 | bits<5> Rd; | |
3417 | bits<5> Rn; | |
3418 | bits<6> scale; | |
3419 | let Inst{30-29} = 0b00; | |
3420 | let Inst{28-24} = 0b11110; | |
3421 | let Inst{23-22} = type; | |
3422 | let Inst{21} = 0; | |
3423 | let Inst{20-19} = rmode; | |
3424 | let Inst{18-16} = opcode; | |
3425 | let Inst{15-10} = scale; | |
3426 | let Inst{9-5} = Rn; | |
3427 | let Inst{4-0} = Rd; | |
3428 | } | |
3429 | ||
3430 | multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm, | |
3431 | SDPatternOperator OpN> { | |
3432 | // Unscaled single-precision to 32-bit | |
3433 | def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm, | |
3434 | [(set GPR32:$Rd, (OpN FPR32:$Rn))]> { | |
3435 | let Inst{31} = 0; // 32-bit GPR flag | |
3436 | } | |
3437 | ||
3438 | // Unscaled single-precision to 64-bit | |
3439 | def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm, | |
3440 | [(set GPR64:$Rd, (OpN FPR32:$Rn))]> { | |
3441 | let Inst{31} = 1; // 64-bit GPR flag | |
3442 | } | |
3443 | ||
3444 | // Unscaled double-precision to 32-bit | |
3445 | def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm, | |
3446 | [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> { | |
3447 | let Inst{31} = 0; // 32-bit GPR flag | |
3448 | } | |
3449 | ||
3450 | // Unscaled double-precision to 64-bit | |
3451 | def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm, | |
3452 | [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> { | |
3453 | let Inst{31} = 1; // 64-bit GPR flag | |
3454 | } | |
3455 | } | |
3456 | ||
3457 | multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm, | |
3458 | SDPatternOperator OpN> { | |
3459 | // Scaled single-precision to 32-bit | |
3460 | def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32, | |
3461 | fixedpoint_f32_i32, asm, | |
3462 | [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn, | |
3463 | fixedpoint_f32_i32:$scale)))]> { | |
3464 | let Inst{31} = 0; // 32-bit GPR flag | |
3465 | let scale{5} = 1; | |
3466 | } | |
3467 | ||
3468 | // Scaled single-precision to 64-bit | |
3469 | def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64, | |
3470 | fixedpoint_f32_i64, asm, | |
3471 | [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn, | |
3472 | fixedpoint_f32_i64:$scale)))]> { | |
3473 | let Inst{31} = 1; // 64-bit GPR flag | |
3474 | } | |
3475 | ||
3476 | // Scaled double-precision to 32-bit | |
3477 | def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32, | |
3478 | fixedpoint_f64_i32, asm, | |
3479 | [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn, | |
3480 | fixedpoint_f64_i32:$scale)))]> { | |
3481 | let Inst{31} = 0; // 32-bit GPR flag | |
3482 | let scale{5} = 1; | |
3483 | } | |
3484 | ||
3485 | // Scaled double-precision to 64-bit | |
3486 | def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64, | |
3487 | fixedpoint_f64_i64, asm, | |
3488 | [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn, | |
3489 | fixedpoint_f64_i64:$scale)))]> { | |
3490 | let Inst{31} = 1; // 64-bit GPR flag | |
3491 | } | |
3492 | } | |
3493 | ||
3494 | //--- | |
3495 | // Integer to floating point conversion | |
3496 | //--- | |
3497 | ||
3498 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
3499 | class BaseIntegerToFP<bit isUnsigned, | |
3500 | RegisterClass srcType, RegisterClass dstType, | |
3501 | Operand immType, string asm, list<dag> pattern> | |
3502 | : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale), | |
3503 | asm, "\t$Rd, $Rn, $scale", "", pattern>, | |
3504 | Sched<[WriteFCvt]> { | |
3505 | bits<5> Rd; | |
3506 | bits<5> Rn; | |
3507 | bits<6> scale; | |
3508 | let Inst{30-23} = 0b00111100; | |
3509 | let Inst{21-17} = 0b00001; | |
3510 | let Inst{16} = isUnsigned; | |
3511 | let Inst{15-10} = scale; | |
3512 | let Inst{9-5} = Rn; | |
3513 | let Inst{4-0} = Rd; | |
3514 | } | |
3515 | ||
3516 | class BaseIntegerToFPUnscaled<bit isUnsigned, | |
3517 | RegisterClass srcType, RegisterClass dstType, | |
3518 | ValueType dvt, string asm, SDNode node> | |
3519 | : I<(outs dstType:$Rd), (ins srcType:$Rn), | |
3520 | asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>, | |
3521 | Sched<[WriteFCvt]> { | |
3522 | bits<5> Rd; | |
3523 | bits<5> Rn; | |
3524 | bits<6> scale; | |
3525 | let Inst{30-23} = 0b00111100; | |
3526 | let Inst{21-17} = 0b10001; | |
3527 | let Inst{16} = isUnsigned; | |
3528 | let Inst{15-10} = 0b000000; | |
3529 | let Inst{9-5} = Rn; | |
3530 | let Inst{4-0} = Rd; | |
3531 | } | |
3532 | ||
3533 | multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> { | |
3534 | // Unscaled | |
3535 | def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> { | |
3536 | let Inst{31} = 0; // 32-bit GPR flag | |
3537 | let Inst{22} = 0; // 32-bit FPR flag | |
3538 | } | |
3539 | ||
3540 | def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> { | |
3541 | let Inst{31} = 0; // 32-bit GPR flag | |
3542 | let Inst{22} = 1; // 64-bit FPR flag | |
3543 | } | |
3544 | ||
3545 | def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> { | |
3546 | let Inst{31} = 1; // 64-bit GPR flag | |
3547 | let Inst{22} = 0; // 32-bit FPR flag | |
3548 | } | |
3549 | ||
3550 | def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> { | |
3551 | let Inst{31} = 1; // 64-bit GPR flag | |
3552 | let Inst{22} = 1; // 64-bit FPR flag | |
3553 | } | |
3554 | ||
3555 | // Scaled | |
3556 | def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm, | |
3557 | [(set FPR32:$Rd, | |
3558 | (fdiv (node GPR32:$Rn), | |
3559 | fixedpoint_f32_i32:$scale))]> { | |
3560 | let Inst{31} = 0; // 32-bit GPR flag | |
3561 | let Inst{22} = 0; // 32-bit FPR flag | |
3562 | let scale{5} = 1; | |
3563 | } | |
3564 | ||
3565 | def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm, | |
3566 | [(set FPR64:$Rd, | |
3567 | (fdiv (node GPR32:$Rn), | |
3568 | fixedpoint_f64_i32:$scale))]> { | |
3569 | let Inst{31} = 0; // 32-bit GPR flag | |
3570 | let Inst{22} = 1; // 64-bit FPR flag | |
3571 | let scale{5} = 1; | |
3572 | } | |
3573 | ||
3574 | def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm, | |
3575 | [(set FPR32:$Rd, | |
3576 | (fdiv (node GPR64:$Rn), | |
3577 | fixedpoint_f32_i64:$scale))]> { | |
3578 | let Inst{31} = 1; // 64-bit GPR flag | |
3579 | let Inst{22} = 0; // 32-bit FPR flag | |
3580 | } | |
3581 | ||
3582 | def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm, | |
3583 | [(set FPR64:$Rd, | |
3584 | (fdiv (node GPR64:$Rn), | |
3585 | fixedpoint_f64_i64:$scale))]> { | |
3586 | let Inst{31} = 1; // 64-bit GPR flag | |
3587 | let Inst{22} = 1; // 64-bit FPR flag | |
3588 | } | |
3589 | } | |
3590 | ||
3591 | //--- | |
3592 | // Unscaled integer <-> floating point conversion (i.e. FMOV) | |
3593 | //--- | |
3594 | ||
3595 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3596 | class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode, | |
3597 | RegisterClass srcType, RegisterClass dstType, | |
3598 | string asm> | |
3599 | : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", | |
3600 | // We use COPY_TO_REGCLASS for these bitconvert operations. | |
3601 | // copyPhysReg() expands the resultant COPY instructions after | |
3602 | // regalloc is done. This gives greater freedom for the allocator | |
3603 | // and related passes (coalescing, copy propagation, et. al.) to | |
3604 | // be more effective. | |
3605 | [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>, | |
3606 | Sched<[WriteFCopy]> { | |
3607 | bits<5> Rd; | |
3608 | bits<5> Rn; | |
3609 | let Inst{30-23} = 0b00111100; | |
3610 | let Inst{21} = 1; | |
3611 | let Inst{20-19} = rmode; | |
3612 | let Inst{18-16} = opcode; | |
3613 | let Inst{15-10} = 0b000000; | |
3614 | let Inst{9-5} = Rn; | |
3615 | let Inst{4-0} = Rd; | |
3616 | } | |
3617 | ||
3618 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3619 | class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode, | |
3620 | RegisterClass srcType, RegisterOperand dstType, string asm, | |
3621 | string kind> | |
3622 | : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm, | |
3623 | "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>, | |
3624 | Sched<[WriteFCopy]> { | |
3625 | bits<5> Rd; | |
3626 | bits<5> Rn; | |
3627 | let Inst{30-23} = 0b00111101; | |
3628 | let Inst{21} = 1; | |
3629 | let Inst{20-19} = rmode; | |
3630 | let Inst{18-16} = opcode; | |
3631 | let Inst{15-10} = 0b000000; | |
3632 | let Inst{9-5} = Rn; | |
3633 | let Inst{4-0} = Rd; | |
3634 | ||
3635 | let DecoderMethod = "DecodeFMOVLaneInstruction"; | |
3636 | } | |
3637 | ||
3638 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3639 | class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode, | |
3640 | RegisterOperand srcType, RegisterClass dstType, string asm, | |
3641 | string kind> | |
3642 | : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm, | |
3643 | "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>, | |
3644 | Sched<[WriteFCopy]> { | |
3645 | bits<5> Rd; | |
3646 | bits<5> Rn; | |
3647 | let Inst{30-23} = 0b00111101; | |
3648 | let Inst{21} = 1; | |
3649 | let Inst{20-19} = rmode; | |
3650 | let Inst{18-16} = opcode; | |
3651 | let Inst{15-10} = 0b000000; | |
3652 | let Inst{9-5} = Rn; | |
3653 | let Inst{4-0} = Rd; | |
3654 | ||
3655 | let DecoderMethod = "DecodeFMOVLaneInstruction"; | |
3656 | } | |
3657 | ||
3658 | ||
3659 | ||
3660 | multiclass UnscaledConversion<string asm> { | |
3661 | def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> { | |
3662 | let Inst{31} = 0; // 32-bit GPR flag | |
3663 | let Inst{22} = 0; // 32-bit FPR flag | |
3664 | } | |
3665 | ||
3666 | def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> { | |
3667 | let Inst{31} = 1; // 64-bit GPR flag | |
3668 | let Inst{22} = 1; // 64-bit FPR flag | |
3669 | } | |
3670 | ||
3671 | def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> { | |
3672 | let Inst{31} = 0; // 32-bit GPR flag | |
3673 | let Inst{22} = 0; // 32-bit FPR flag | |
3674 | } | |
3675 | ||
3676 | def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> { | |
3677 | let Inst{31} = 1; // 64-bit GPR flag | |
3678 | let Inst{22} = 1; // 64-bit FPR flag | |
3679 | } | |
3680 | ||
3681 | def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128, | |
3682 | asm, ".d"> { | |
3683 | let Inst{31} = 1; | |
3684 | let Inst{22} = 0; | |
3685 | } | |
3686 | ||
3687 | def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64, | |
3688 | asm, ".d"> { | |
3689 | let Inst{31} = 1; | |
3690 | let Inst{22} = 0; | |
3691 | } | |
3692 | } | |
3693 | ||
3694 | //--- | |
3695 | // Floating point conversion | |
3696 | //--- | |
3697 | ||
3698 | class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType, | |
3699 | RegisterClass srcType, string asm, list<dag> pattern> | |
3700 | : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>, | |
3701 | Sched<[WriteFCvt]> { | |
3702 | bits<5> Rd; | |
3703 | bits<5> Rn; | |
3704 | let Inst{31-24} = 0b00011110; | |
3705 | let Inst{23-22} = type; | |
3706 | let Inst{21-17} = 0b10001; | |
3707 | let Inst{16-15} = opcode; | |
3708 | let Inst{14-10} = 0b10000; | |
3709 | let Inst{9-5} = Rn; | |
3710 | let Inst{4-0} = Rd; | |
3711 | } | |
3712 | ||
3713 | multiclass FPConversion<string asm> { | |
3714 | // Double-precision to Half-precision | |
3715 | def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, | |
3716 | [(set FPR16:$Rd, (fround FPR64:$Rn))]>; | |
3717 | ||
3718 | // Double-precision to Single-precision | |
3719 | def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm, | |
3720 | [(set FPR32:$Rd, (fround FPR64:$Rn))]>; | |
3721 | ||
3722 | // Half-precision to Double-precision | |
3723 | def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, | |
3724 | [(set FPR64:$Rd, (fextend FPR16:$Rn))]>; | |
3725 | ||
3726 | // Half-precision to Single-precision | |
3727 | def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, | |
3728 | [(set FPR32:$Rd, (fextend FPR16:$Rn))]>; | |
3729 | ||
3730 | // Single-precision to Double-precision | |
3731 | def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm, | |
3732 | [(set FPR64:$Rd, (fextend FPR32:$Rn))]>; | |
3733 | ||
3734 | // Single-precision to Half-precision | |
3735 | def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, | |
3736 | [(set FPR16:$Rd, (fround FPR32:$Rn))]>; | |
3737 | } | |
3738 | ||
3739 | //--- | |
3740 | // Single operand floating point data processing | |
3741 | //--- | |
3742 | ||
3743 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3744 | class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype, | |
3745 | ValueType vt, string asm, SDPatternOperator node> | |
3746 | : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "", | |
3747 | [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>, | |
3748 | Sched<[WriteF]> { | |
3749 | bits<5> Rd; | |
3750 | bits<5> Rn; | |
3751 | let Inst{31-23} = 0b000111100; | |
3752 | let Inst{21-19} = 0b100; | |
3753 | let Inst{18-15} = opcode; | |
3754 | let Inst{14-10} = 0b10000; | |
3755 | let Inst{9-5} = Rn; | |
3756 | let Inst{4-0} = Rd; | |
3757 | } | |
3758 | ||
3759 | multiclass SingleOperandFPData<bits<4> opcode, string asm, | |
3760 | SDPatternOperator node = null_frag> { | |
3761 | def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> { | |
3762 | let Inst{22} = 0; // 32-bit size flag | |
3763 | } | |
3764 | ||
3765 | def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> { | |
3766 | let Inst{22} = 1; // 64-bit size flag | |
3767 | } | |
3768 | } | |
3769 | ||
3770 | //--- | |
3771 | // Two operand floating point data processing | |
3772 | //--- | |
3773 | ||
3774 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3775 | class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype, | |
3776 | string asm, list<dag> pat> | |
3777 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), | |
3778 | asm, "\t$Rd, $Rn, $Rm", "", pat>, | |
3779 | Sched<[WriteF]> { | |
3780 | bits<5> Rd; | |
3781 | bits<5> Rn; | |
3782 | bits<5> Rm; | |
3783 | let Inst{31-23} = 0b000111100; | |
3784 | let Inst{21} = 1; | |
3785 | let Inst{20-16} = Rm; | |
3786 | let Inst{15-12} = opcode; | |
3787 | let Inst{11-10} = 0b10; | |
3788 | let Inst{9-5} = Rn; | |
3789 | let Inst{4-0} = Rd; | |
3790 | } | |
3791 | ||
3792 | multiclass TwoOperandFPData<bits<4> opcode, string asm, | |
3793 | SDPatternOperator node = null_frag> { | |
3794 | def Srr : BaseTwoOperandFPData<opcode, FPR32, asm, | |
3795 | [(set (f32 FPR32:$Rd), | |
3796 | (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> { | |
3797 | let Inst{22} = 0; // 32-bit size flag | |
3798 | } | |
3799 | ||
3800 | def Drr : BaseTwoOperandFPData<opcode, FPR64, asm, | |
3801 | [(set (f64 FPR64:$Rd), | |
3802 | (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> { | |
3803 | let Inst{22} = 1; // 64-bit size flag | |
3804 | } | |
3805 | } | |
3806 | ||
3807 | multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> { | |
3808 | def Srr : BaseTwoOperandFPData<opcode, FPR32, asm, | |
3809 | [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> { | |
3810 | let Inst{22} = 0; // 32-bit size flag | |
3811 | } | |
3812 | ||
3813 | def Drr : BaseTwoOperandFPData<opcode, FPR64, asm, | |
3814 | [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> { | |
3815 | let Inst{22} = 1; // 64-bit size flag | |
3816 | } | |
3817 | } | |
3818 | ||
3819 | ||
3820 | //--- | |
3821 | // Three operand floating point data processing | |
3822 | //--- | |
3823 | ||
3824 | class BaseThreeOperandFPData<bit isNegated, bit isSub, | |
3825 | RegisterClass regtype, string asm, list<dag> pat> | |
3826 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra), | |
3827 | asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>, | |
3828 | Sched<[WriteFMul]> { | |
3829 | bits<5> Rd; | |
3830 | bits<5> Rn; | |
3831 | bits<5> Rm; | |
3832 | bits<5> Ra; | |
3833 | let Inst{31-23} = 0b000111110; | |
3834 | let Inst{21} = isNegated; | |
3835 | let Inst{20-16} = Rm; | |
3836 | let Inst{15} = isSub; | |
3837 | let Inst{14-10} = Ra; | |
3838 | let Inst{9-5} = Rn; | |
3839 | let Inst{4-0} = Rd; | |
3840 | } | |
3841 | ||
3842 | multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm, | |
3843 | SDPatternOperator node> { | |
3844 | def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm, | |
3845 | [(set FPR32:$Rd, | |
3846 | (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> { | |
3847 | let Inst{22} = 0; // 32-bit size flag | |
3848 | } | |
3849 | ||
3850 | def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm, | |
3851 | [(set FPR64:$Rd, | |
3852 | (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> { | |
3853 | let Inst{22} = 1; // 64-bit size flag | |
3854 | } | |
3855 | } | |
3856 | ||
3857 | //--- | |
3858 | // Floating point data comparisons | |
3859 | //--- | |
3860 | ||
3861 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3862 | class BaseOneOperandFPComparison<bit signalAllNans, | |
3863 | RegisterClass regtype, string asm, | |
3864 | list<dag> pat> | |
3865 | : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>, | |
3866 | Sched<[WriteFCmp]> { | |
3867 | bits<5> Rn; | |
3868 | let Inst{31-23} = 0b000111100; | |
3869 | let Inst{21} = 1; | |
3870 | ||
3871 | let Inst{15-10} = 0b001000; | |
3872 | let Inst{9-5} = Rn; | |
3873 | let Inst{4} = signalAllNans; | |
3874 | let Inst{3-0} = 0b1000; | |
3875 | ||
3876 | // Rm should be 0b00000 canonically, but we need to accept any value. | |
3877 | let PostEncoderMethod = "fixOneOperandFPComparison"; | |
3878 | } | |
3879 | ||
3880 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3881 | class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype, | |
3882 | string asm, list<dag> pat> | |
3883 | : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>, | |
3884 | Sched<[WriteFCmp]> { | |
3885 | bits<5> Rm; | |
3886 | bits<5> Rn; | |
3887 | let Inst{31-23} = 0b000111100; | |
3888 | let Inst{21} = 1; | |
3889 | let Inst{20-16} = Rm; | |
3890 | let Inst{15-10} = 0b001000; | |
3891 | let Inst{9-5} = Rn; | |
3892 | let Inst{4} = signalAllNans; | |
3893 | let Inst{3-0} = 0b0000; | |
3894 | } | |
3895 | ||
3896 | multiclass FPComparison<bit signalAllNans, string asm, | |
3897 | SDPatternOperator OpNode = null_frag> { | |
3898 | let Defs = [NZCV] in { | |
3899 | def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm, | |
3900 | [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> { | |
3901 | let Inst{22} = 0; | |
3902 | } | |
3903 | ||
3904 | def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm, | |
3905 | [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> { | |
3906 | let Inst{22} = 0; | |
3907 | } | |
3908 | ||
3909 | def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm, | |
3910 | [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> { | |
3911 | let Inst{22} = 1; | |
3912 | } | |
3913 | ||
3914 | def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm, | |
3915 | [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> { | |
3916 | let Inst{22} = 1; | |
3917 | } | |
3918 | } // Defs = [NZCV] | |
3919 | } | |
3920 | ||
3921 | //--- | |
3922 | // Floating point conditional comparisons | |
3923 | //--- | |
3924 | ||
3925 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
3926 | class BaseFPCondComparison<bit signalAllNans, | |
3927 | RegisterClass regtype, string asm> | |
3928 | : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond), | |
3929 | asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>, | |
3930 | Sched<[WriteFCmp]> { | |
3931 | bits<5> Rn; | |
3932 | bits<5> Rm; | |
3933 | bits<4> nzcv; | |
3934 | bits<4> cond; | |
3935 | ||
3936 | let Inst{31-23} = 0b000111100; | |
3937 | let Inst{21} = 1; | |
3938 | let Inst{20-16} = Rm; | |
3939 | let Inst{15-12} = cond; | |
3940 | let Inst{11-10} = 0b01; | |
3941 | let Inst{9-5} = Rn; | |
3942 | let Inst{4} = signalAllNans; | |
3943 | let Inst{3-0} = nzcv; | |
3944 | } | |
3945 | ||
3946 | multiclass FPCondComparison<bit signalAllNans, string asm> { | |
3947 | let Defs = [NZCV], Uses = [NZCV] in { | |
3948 | def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> { | |
3949 | let Inst{22} = 0; | |
3950 | } | |
3951 | ||
3952 | def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> { | |
3953 | let Inst{22} = 1; | |
3954 | } | |
3955 | } // Defs = [NZCV], Uses = [NZCV] | |
3956 | } | |
3957 | ||
3958 | //--- | |
3959 | // Floating point conditional select | |
3960 | //--- | |
3961 | ||
3962 | class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm> | |
3963 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond), | |
3964 | asm, "\t$Rd, $Rn, $Rm, $cond", "", | |
3965 | [(set regtype:$Rd, | |
3966 | (AArch64csel (vt regtype:$Rn), regtype:$Rm, | |
3967 | (i32 imm:$cond), NZCV))]>, | |
3968 | Sched<[WriteF]> { | |
3969 | bits<5> Rd; | |
3970 | bits<5> Rn; | |
3971 | bits<5> Rm; | |
3972 | bits<4> cond; | |
3973 | ||
3974 | let Inst{31-23} = 0b000111100; | |
3975 | let Inst{21} = 1; | |
3976 | let Inst{20-16} = Rm; | |
3977 | let Inst{15-12} = cond; | |
3978 | let Inst{11-10} = 0b11; | |
3979 | let Inst{9-5} = Rn; | |
3980 | let Inst{4-0} = Rd; | |
3981 | } | |
3982 | ||
3983 | multiclass FPCondSelect<string asm> { | |
3984 | let Uses = [NZCV] in { | |
3985 | def Srrr : BaseFPCondSelect<FPR32, f32, asm> { | |
3986 | let Inst{22} = 0; | |
3987 | } | |
3988 | ||
3989 | def Drrr : BaseFPCondSelect<FPR64, f64, asm> { | |
3990 | let Inst{22} = 1; | |
3991 | } | |
3992 | } // Uses = [NZCV] | |
3993 | } | |
3994 | ||
3995 | //--- | |
3996 | // Floating move immediate | |
3997 | //--- | |
3998 | ||
3999 | class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm> | |
4000 | : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "", | |
4001 | [(set regtype:$Rd, fpimmtype:$imm)]>, | |
4002 | Sched<[WriteFImm]> { | |
4003 | bits<5> Rd; | |
4004 | bits<8> imm; | |
4005 | let Inst{31-23} = 0b000111100; | |
4006 | let Inst{21} = 1; | |
4007 | let Inst{20-13} = imm; | |
4008 | let Inst{12-5} = 0b10000000; | |
4009 | let Inst{4-0} = Rd; | |
4010 | } | |
4011 | ||
4012 | multiclass FPMoveImmediate<string asm> { | |
4013 | def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> { | |
4014 | let Inst{22} = 0; | |
4015 | } | |
4016 | ||
4017 | def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> { | |
4018 | let Inst{22} = 1; | |
4019 | } | |
4020 | } | |
4021 | } // end of 'let Predicates = [HasFPARMv8]' | |
4022 | ||
4023 | //---------------------------------------------------------------------------- | |
4024 | // AdvSIMD | |
4025 | //---------------------------------------------------------------------------- | |
4026 | ||
4027 | let Predicates = [HasNEON] in { | |
4028 | ||
4029 | //---------------------------------------------------------------------------- | |
4030 | // AdvSIMD three register vector instructions | |
4031 | //---------------------------------------------------------------------------- | |
4032 | ||
4033 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4034 | class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4035 | RegisterOperand regtype, string asm, string kind, | |
4036 | list<dag> pattern> | |
4037 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm, | |
4038 | "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # | |
4039 | "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>, | |
4040 | Sched<[WriteV]> { | |
4041 | bits<5> Rd; | |
4042 | bits<5> Rn; | |
4043 | bits<5> Rm; | |
4044 | let Inst{31} = 0; | |
4045 | let Inst{30} = Q; | |
4046 | let Inst{29} = U; | |
4047 | let Inst{28-24} = 0b01110; | |
4048 | let Inst{23-22} = size; | |
4049 | let Inst{21} = 1; | |
4050 | let Inst{20-16} = Rm; | |
4051 | let Inst{15-11} = opcode; | |
4052 | let Inst{10} = 1; | |
4053 | let Inst{9-5} = Rn; | |
4054 | let Inst{4-0} = Rd; | |
4055 | } | |
4056 | ||
4057 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4058 | class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4059 | RegisterOperand regtype, string asm, string kind, | |
4060 | list<dag> pattern> | |
4061 | : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm, | |
4062 | "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # | |
4063 | "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>, | |
4064 | Sched<[WriteV]> { | |
4065 | bits<5> Rd; | |
4066 | bits<5> Rn; | |
4067 | bits<5> Rm; | |
4068 | let Inst{31} = 0; | |
4069 | let Inst{30} = Q; | |
4070 | let Inst{29} = U; | |
4071 | let Inst{28-24} = 0b01110; | |
4072 | let Inst{23-22} = size; | |
4073 | let Inst{21} = 1; | |
4074 | let Inst{20-16} = Rm; | |
4075 | let Inst{15-11} = opcode; | |
4076 | let Inst{10} = 1; | |
4077 | let Inst{9-5} = Rn; | |
4078 | let Inst{4-0} = Rd; | |
4079 | } | |
4080 | ||
4081 | // All operand sizes distinguished in the encoding. | |
4082 | multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm, | |
4083 | SDPatternOperator OpNode> { | |
4084 | def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64, | |
4085 | asm, ".8b", | |
4086 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
4087 | def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128, | |
4088 | asm, ".16b", | |
4089 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>; | |
4090 | def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64, | |
4091 | asm, ".4h", | |
4092 | [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>; | |
4093 | def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128, | |
4094 | asm, ".8h", | |
4095 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>; | |
4096 | def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64, | |
4097 | asm, ".2s", | |
4098 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>; | |
4099 | def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128, | |
4100 | asm, ".4s", | |
4101 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>; | |
4102 | def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128, | |
4103 | asm, ".2d", | |
4104 | [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>; | |
4105 | } | |
4106 | ||
4107 | // As above, but D sized elements unsupported. | |
4108 | multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm, | |
4109 | SDPatternOperator OpNode> { | |
4110 | def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64, | |
4111 | asm, ".8b", | |
4112 | [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>; | |
4113 | def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128, | |
4114 | asm, ".16b", | |
4115 | [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>; | |
4116 | def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64, | |
4117 | asm, ".4h", | |
4118 | [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>; | |
4119 | def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128, | |
4120 | asm, ".8h", | |
4121 | [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>; | |
4122 | def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64, | |
4123 | asm, ".2s", | |
4124 | [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>; | |
4125 | def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128, | |
4126 | asm, ".4s", | |
4127 | [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>; | |
4128 | } | |
4129 | ||
4130 | multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm, | |
4131 | SDPatternOperator OpNode> { | |
4132 | def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64, | |
4133 | asm, ".8b", | |
4134 | [(set (v8i8 V64:$dst), | |
4135 | (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
4136 | def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128, | |
4137 | asm, ".16b", | |
4138 | [(set (v16i8 V128:$dst), | |
4139 | (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>; | |
4140 | def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64, | |
4141 | asm, ".4h", | |
4142 | [(set (v4i16 V64:$dst), | |
4143 | (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>; | |
4144 | def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128, | |
4145 | asm, ".8h", | |
4146 | [(set (v8i16 V128:$dst), | |
4147 | (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>; | |
4148 | def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64, | |
4149 | asm, ".2s", | |
4150 | [(set (v2i32 V64:$dst), | |
4151 | (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>; | |
4152 | def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128, | |
4153 | asm, ".4s", | |
4154 | [(set (v4i32 V128:$dst), | |
4155 | (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>; | |
4156 | } | |
4157 | ||
4158 | // As above, but only B sized elements supported. | |
4159 | multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm, | |
4160 | SDPatternOperator OpNode> { | |
4161 | def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64, | |
4162 | asm, ".8b", | |
4163 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
4164 | def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128, | |
4165 | asm, ".16b", | |
4166 | [(set (v16i8 V128:$Rd), | |
4167 | (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>; | |
4168 | } | |
4169 | ||
4170 | // As above, but only S and D sized floating point elements supported. | |
4171 | multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc, | |
4172 | string asm, SDPatternOperator OpNode> { | |
4173 | def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64, | |
4174 | asm, ".2s", | |
4175 | [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>; | |
4176 | def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128, | |
4177 | asm, ".4s", | |
4178 | [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>; | |
4179 | def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128, | |
4180 | asm, ".2d", | |
4181 | [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>; | |
4182 | } | |
4183 | ||
4184 | multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc, | |
4185 | string asm, | |
4186 | SDPatternOperator OpNode> { | |
4187 | def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64, | |
4188 | asm, ".2s", | |
4189 | [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>; | |
4190 | def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128, | |
4191 | asm, ".4s", | |
4192 | [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>; | |
4193 | def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128, | |
4194 | asm, ".2d", | |
4195 | [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>; | |
4196 | } | |
4197 | ||
4198 | multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc, | |
4199 | string asm, SDPatternOperator OpNode> { | |
4200 | def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64, | |
4201 | asm, ".2s", | |
4202 | [(set (v2f32 V64:$dst), | |
4203 | (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>; | |
4204 | def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128, | |
4205 | asm, ".4s", | |
4206 | [(set (v4f32 V128:$dst), | |
4207 | (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>; | |
4208 | def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128, | |
4209 | asm, ".2d", | |
4210 | [(set (v2f64 V128:$dst), | |
4211 | (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>; | |
4212 | } | |
4213 | ||
4214 | // As above, but D and B sized elements unsupported. | |
4215 | multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm, | |
4216 | SDPatternOperator OpNode> { | |
4217 | def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64, | |
4218 | asm, ".4h", | |
4219 | [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>; | |
4220 | def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128, | |
4221 | asm, ".8h", | |
4222 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>; | |
4223 | def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64, | |
4224 | asm, ".2s", | |
4225 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>; | |
4226 | def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128, | |
4227 | asm, ".4s", | |
4228 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>; | |
4229 | } | |
4230 | ||
4231 | // Logical three vector ops share opcode bits, and only use B sized elements. | |
4232 | multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm, | |
4233 | SDPatternOperator OpNode = null_frag> { | |
4234 | def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64, | |
4235 | asm, ".8b", | |
4236 | [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>; | |
4237 | def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128, | |
4238 | asm, ".16b", | |
4239 | [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>; | |
4240 | ||
4241 | def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)), | |
4242 | (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>; | |
4243 | def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)), | |
4244 | (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>; | |
4245 | def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)), | |
4246 | (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>; | |
4247 | ||
4248 | def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)), | |
4249 | (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>; | |
4250 | def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)), | |
4251 | (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>; | |
4252 | def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)), | |
4253 | (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>; | |
4254 | } | |
4255 | ||
4256 | multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size, | |
4257 | string asm, SDPatternOperator OpNode> { | |
4258 | def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64, | |
4259 | asm, ".8b", | |
4260 | [(set (v8i8 V64:$dst), | |
4261 | (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
4262 | def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128, | |
4263 | asm, ".16b", | |
4264 | [(set (v16i8 V128:$dst), | |
4265 | (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), | |
4266 | (v16i8 V128:$Rm)))]>; | |
4267 | ||
4268 | def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS), | |
4269 | (v4i16 V64:$RHS))), | |
4270 | (!cast<Instruction>(NAME#"v8i8") | |
4271 | V64:$LHS, V64:$MHS, V64:$RHS)>; | |
4272 | def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS), | |
4273 | (v2i32 V64:$RHS))), | |
4274 | (!cast<Instruction>(NAME#"v8i8") | |
4275 | V64:$LHS, V64:$MHS, V64:$RHS)>; | |
4276 | def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS), | |
4277 | (v1i64 V64:$RHS))), | |
4278 | (!cast<Instruction>(NAME#"v8i8") | |
4279 | V64:$LHS, V64:$MHS, V64:$RHS)>; | |
4280 | ||
4281 | def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS), | |
4282 | (v8i16 V128:$RHS))), | |
4283 | (!cast<Instruction>(NAME#"v16i8") | |
4284 | V128:$LHS, V128:$MHS, V128:$RHS)>; | |
4285 | def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS), | |
4286 | (v4i32 V128:$RHS))), | |
4287 | (!cast<Instruction>(NAME#"v16i8") | |
4288 | V128:$LHS, V128:$MHS, V128:$RHS)>; | |
4289 | def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS), | |
4290 | (v2i64 V128:$RHS))), | |
4291 | (!cast<Instruction>(NAME#"v16i8") | |
4292 | V128:$LHS, V128:$MHS, V128:$RHS)>; | |
4293 | } | |
4294 | ||
4295 | ||
4296 | //---------------------------------------------------------------------------- | |
4297 | // AdvSIMD two register vector instructions. | |
4298 | //---------------------------------------------------------------------------- | |
4299 | ||
4300 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4301 | class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4302 | RegisterOperand regtype, string asm, string dstkind, | |
4303 | string srckind, list<dag> pattern> | |
4304 | : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, | |
4305 | "{\t$Rd" # dstkind # ", $Rn" # srckind # | |
4306 | "|" # dstkind # "\t$Rd, $Rn}", "", pattern>, | |
4307 | Sched<[WriteV]> { | |
4308 | bits<5> Rd; | |
4309 | bits<5> Rn; | |
4310 | let Inst{31} = 0; | |
4311 | let Inst{30} = Q; | |
4312 | let Inst{29} = U; | |
4313 | let Inst{28-24} = 0b01110; | |
4314 | let Inst{23-22} = size; | |
4315 | let Inst{21-17} = 0b10000; | |
4316 | let Inst{16-12} = opcode; | |
4317 | let Inst{11-10} = 0b10; | |
4318 | let Inst{9-5} = Rn; | |
4319 | let Inst{4-0} = Rd; | |
4320 | } | |
4321 | ||
4322 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4323 | class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4324 | RegisterOperand regtype, string asm, string dstkind, | |
4325 | string srckind, list<dag> pattern> | |
4326 | : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm, | |
4327 | "{\t$Rd" # dstkind # ", $Rn" # srckind # | |
4328 | "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>, | |
4329 | Sched<[WriteV]> { | |
4330 | bits<5> Rd; | |
4331 | bits<5> Rn; | |
4332 | let Inst{31} = 0; | |
4333 | let Inst{30} = Q; | |
4334 | let Inst{29} = U; | |
4335 | let Inst{28-24} = 0b01110; | |
4336 | let Inst{23-22} = size; | |
4337 | let Inst{21-17} = 0b10000; | |
4338 | let Inst{16-12} = opcode; | |
4339 | let Inst{11-10} = 0b10; | |
4340 | let Inst{9-5} = Rn; | |
4341 | let Inst{4-0} = Rd; | |
4342 | } | |
4343 | ||
4344 | // Supports B, H, and S element sizes. | |
4345 | multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm, | |
4346 | SDPatternOperator OpNode> { | |
4347 | def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64, | |
4348 | asm, ".8b", ".8b", | |
4349 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>; | |
4350 | def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128, | |
4351 | asm, ".16b", ".16b", | |
4352 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>; | |
4353 | def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64, | |
4354 | asm, ".4h", ".4h", | |
4355 | [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>; | |
4356 | def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128, | |
4357 | asm, ".8h", ".8h", | |
4358 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>; | |
4359 | def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64, | |
4360 | asm, ".2s", ".2s", | |
4361 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>; | |
4362 | def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128, | |
4363 | asm, ".4s", ".4s", | |
4364 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>; | |
4365 | } | |
4366 | ||
4367 | class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size, | |
4368 | RegisterOperand regtype, string asm, string dstkind, | |
4369 | string srckind, string amount> | |
4370 | : I<(outs V128:$Rd), (ins regtype:$Rn), asm, | |
4371 | "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount # | |
4372 | "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>, | |
4373 | Sched<[WriteV]> { | |
4374 | bits<5> Rd; | |
4375 | bits<5> Rn; | |
4376 | let Inst{31} = 0; | |
4377 | let Inst{30} = Q; | |
4378 | let Inst{29-24} = 0b101110; | |
4379 | let Inst{23-22} = size; | |
4380 | let Inst{21-10} = 0b100001001110; | |
4381 | let Inst{9-5} = Rn; | |
4382 | let Inst{4-0} = Rd; | |
4383 | } | |
4384 | ||
4385 | multiclass SIMDVectorLShiftLongBySizeBHS { | |
85aaf69f | 4386 | let hasSideEffects = 0 in { |
1a4d82fc JJ |
4387 | def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64, |
4388 | "shll", ".8h", ".8b", "8">; | |
4389 | def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128, | |
4390 | "shll2", ".8h", ".16b", "8">; | |
4391 | def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64, | |
4392 | "shll", ".4s", ".4h", "16">; | |
4393 | def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128, | |
4394 | "shll2", ".4s", ".8h", "16">; | |
4395 | def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64, | |
4396 | "shll", ".2d", ".2s", "32">; | |
4397 | def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128, | |
4398 | "shll2", ".2d", ".4s", "32">; | |
4399 | } | |
4400 | } | |
4401 | ||
4402 | // Supports all element sizes. | |
4403 | multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm, | |
4404 | SDPatternOperator OpNode> { | |
4405 | def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64, | |
4406 | asm, ".4h", ".8b", | |
4407 | [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>; | |
4408 | def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128, | |
4409 | asm, ".8h", ".16b", | |
4410 | [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>; | |
4411 | def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64, | |
4412 | asm, ".2s", ".4h", | |
4413 | [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>; | |
4414 | def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128, | |
4415 | asm, ".4s", ".8h", | |
4416 | [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>; | |
4417 | def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64, | |
4418 | asm, ".1d", ".2s", | |
4419 | [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>; | |
4420 | def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128, | |
4421 | asm, ".2d", ".4s", | |
4422 | [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>; | |
4423 | } | |
4424 | ||
4425 | multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm, | |
4426 | SDPatternOperator OpNode> { | |
4427 | def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64, | |
4428 | asm, ".4h", ".8b", | |
4429 | [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), | |
4430 | (v8i8 V64:$Rn)))]>; | |
4431 | def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128, | |
4432 | asm, ".8h", ".16b", | |
4433 | [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), | |
4434 | (v16i8 V128:$Rn)))]>; | |
4435 | def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64, | |
4436 | asm, ".2s", ".4h", | |
4437 | [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), | |
4438 | (v4i16 V64:$Rn)))]>; | |
4439 | def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128, | |
4440 | asm, ".4s", ".8h", | |
4441 | [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), | |
4442 | (v8i16 V128:$Rn)))]>; | |
4443 | def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64, | |
4444 | asm, ".1d", ".2s", | |
4445 | [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd), | |
4446 | (v2i32 V64:$Rn)))]>; | |
4447 | def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128, | |
4448 | asm, ".2d", ".4s", | |
4449 | [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), | |
4450 | (v4i32 V128:$Rn)))]>; | |
4451 | } | |
4452 | ||
4453 | // Supports all element sizes, except 1xD. | |
4454 | multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm, | |
4455 | SDPatternOperator OpNode> { | |
4456 | def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64, | |
4457 | asm, ".8b", ".8b", | |
4458 | [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>; | |
4459 | def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128, | |
4460 | asm, ".16b", ".16b", | |
4461 | [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>; | |
4462 | def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64, | |
4463 | asm, ".4h", ".4h", | |
4464 | [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>; | |
4465 | def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128, | |
4466 | asm, ".8h", ".8h", | |
4467 | [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>; | |
4468 | def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64, | |
4469 | asm, ".2s", ".2s", | |
4470 | [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>; | |
4471 | def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128, | |
4472 | asm, ".4s", ".4s", | |
4473 | [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>; | |
4474 | def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128, | |
4475 | asm, ".2d", ".2d", | |
4476 | [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>; | |
4477 | } | |
4478 | ||
4479 | multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm, | |
4480 | SDPatternOperator OpNode = null_frag> { | |
4481 | def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64, | |
4482 | asm, ".8b", ".8b", | |
4483 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>; | |
4484 | def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128, | |
4485 | asm, ".16b", ".16b", | |
4486 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>; | |
4487 | def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64, | |
4488 | asm, ".4h", ".4h", | |
4489 | [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>; | |
4490 | def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128, | |
4491 | asm, ".8h", ".8h", | |
4492 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>; | |
4493 | def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64, | |
4494 | asm, ".2s", ".2s", | |
4495 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>; | |
4496 | def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128, | |
4497 | asm, ".4s", ".4s", | |
4498 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>; | |
4499 | def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128, | |
4500 | asm, ".2d", ".2d", | |
4501 | [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>; | |
4502 | } | |
4503 | ||
4504 | ||
4505 | // Supports only B element sizes. | |
4506 | multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm, | |
4507 | SDPatternOperator OpNode> { | |
4508 | def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64, | |
4509 | asm, ".8b", ".8b", | |
4510 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>; | |
4511 | def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128, | |
4512 | asm, ".16b", ".16b", | |
4513 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>; | |
4514 | ||
4515 | } | |
4516 | ||
4517 | // Supports only B and H element sizes. | |
4518 | multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm, | |
4519 | SDPatternOperator OpNode> { | |
4520 | def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64, | |
4521 | asm, ".8b", ".8b", | |
4522 | [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>; | |
4523 | def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128, | |
4524 | asm, ".16b", ".16b", | |
4525 | [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>; | |
4526 | def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64, | |
4527 | asm, ".4h", ".4h", | |
4528 | [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>; | |
4529 | def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128, | |
4530 | asm, ".8h", ".8h", | |
4531 | [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>; | |
4532 | } | |
4533 | ||
4534 | // Supports only S and D element sizes, uses high bit of the size field | |
4535 | // as an extra opcode bit. | |
4536 | multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm, | |
4537 | SDPatternOperator OpNode> { | |
4538 | def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64, | |
4539 | asm, ".2s", ".2s", | |
4540 | [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>; | |
4541 | def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128, | |
4542 | asm, ".4s", ".4s", | |
4543 | [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>; | |
4544 | def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128, | |
4545 | asm, ".2d", ".2d", | |
4546 | [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>; | |
4547 | } | |
4548 | ||
4549 | // Supports only S element size. | |
4550 | multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm, | |
4551 | SDPatternOperator OpNode> { | |
4552 | def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64, | |
4553 | asm, ".2s", ".2s", | |
4554 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>; | |
4555 | def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128, | |
4556 | asm, ".4s", ".4s", | |
4557 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>; | |
4558 | } | |
4559 | ||
4560 | ||
4561 | multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm, | |
4562 | SDPatternOperator OpNode> { | |
4563 | def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64, | |
4564 | asm, ".2s", ".2s", | |
4565 | [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>; | |
4566 | def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128, | |
4567 | asm, ".4s", ".4s", | |
4568 | [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>; | |
4569 | def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128, | |
4570 | asm, ".2d", ".2d", | |
4571 | [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>; | |
4572 | } | |
4573 | ||
4574 | multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm, | |
4575 | SDPatternOperator OpNode> { | |
4576 | def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64, | |
4577 | asm, ".2s", ".2s", | |
4578 | [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>; | |
4579 | def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128, | |
4580 | asm, ".4s", ".4s", | |
4581 | [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>; | |
4582 | def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128, | |
4583 | asm, ".2d", ".2d", | |
4584 | [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>; | |
4585 | } | |
4586 | ||
4587 | ||
4588 | class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4589 | RegisterOperand inreg, RegisterOperand outreg, | |
4590 | string asm, string outkind, string inkind, | |
4591 | list<dag> pattern> | |
4592 | : I<(outs outreg:$Rd), (ins inreg:$Rn), asm, | |
4593 | "{\t$Rd" # outkind # ", $Rn" # inkind # | |
4594 | "|" # outkind # "\t$Rd, $Rn}", "", pattern>, | |
4595 | Sched<[WriteV]> { | |
4596 | bits<5> Rd; | |
4597 | bits<5> Rn; | |
4598 | let Inst{31} = 0; | |
4599 | let Inst{30} = Q; | |
4600 | let Inst{29} = U; | |
4601 | let Inst{28-24} = 0b01110; | |
4602 | let Inst{23-22} = size; | |
4603 | let Inst{21-17} = 0b10000; | |
4604 | let Inst{16-12} = opcode; | |
4605 | let Inst{11-10} = 0b10; | |
4606 | let Inst{9-5} = Rn; | |
4607 | let Inst{4-0} = Rd; | |
4608 | } | |
4609 | ||
4610 | class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4611 | RegisterOperand inreg, RegisterOperand outreg, | |
4612 | string asm, string outkind, string inkind, | |
4613 | list<dag> pattern> | |
4614 | : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm, | |
4615 | "{\t$Rd" # outkind # ", $Rn" # inkind # | |
4616 | "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>, | |
4617 | Sched<[WriteV]> { | |
4618 | bits<5> Rd; | |
4619 | bits<5> Rn; | |
4620 | let Inst{31} = 0; | |
4621 | let Inst{30} = Q; | |
4622 | let Inst{29} = U; | |
4623 | let Inst{28-24} = 0b01110; | |
4624 | let Inst{23-22} = size; | |
4625 | let Inst{21-17} = 0b10000; | |
4626 | let Inst{16-12} = opcode; | |
4627 | let Inst{11-10} = 0b10; | |
4628 | let Inst{9-5} = Rn; | |
4629 | let Inst{4-0} = Rd; | |
4630 | } | |
4631 | ||
4632 | multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm, | |
4633 | SDPatternOperator OpNode> { | |
4634 | def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64, | |
4635 | asm, ".8b", ".8h", | |
4636 | [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>; | |
4637 | def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128, | |
4638 | asm#"2", ".16b", ".8h", []>; | |
4639 | def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64, | |
4640 | asm, ".4h", ".4s", | |
4641 | [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>; | |
4642 | def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128, | |
4643 | asm#"2", ".8h", ".4s", []>; | |
4644 | def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64, | |
4645 | asm, ".2s", ".2d", | |
4646 | [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>; | |
4647 | def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128, | |
4648 | asm#"2", ".4s", ".2d", []>; | |
4649 | ||
4650 | def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))), | |
4651 | (!cast<Instruction>(NAME # "v16i8") | |
4652 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>; | |
4653 | def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))), | |
4654 | (!cast<Instruction>(NAME # "v8i16") | |
4655 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>; | |
4656 | def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))), | |
4657 | (!cast<Instruction>(NAME # "v4i32") | |
4658 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>; | |
4659 | } | |
4660 | ||
4661 | class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4662 | RegisterOperand regtype, | |
4663 | string asm, string kind, string zero, | |
4664 | ValueType dty, ValueType sty, SDNode OpNode> | |
4665 | : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, | |
4666 | "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero # | |
4667 | "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "", | |
4668 | [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>, | |
4669 | Sched<[WriteV]> { | |
4670 | bits<5> Rd; | |
4671 | bits<5> Rn; | |
4672 | let Inst{31} = 0; | |
4673 | let Inst{30} = Q; | |
4674 | let Inst{29} = U; | |
4675 | let Inst{28-24} = 0b01110; | |
4676 | let Inst{23-22} = size; | |
4677 | let Inst{21-17} = 0b10000; | |
4678 | let Inst{16-12} = opcode; | |
4679 | let Inst{11-10} = 0b10; | |
4680 | let Inst{9-5} = Rn; | |
4681 | let Inst{4-0} = Rd; | |
4682 | } | |
4683 | ||
4684 | // Comparisons support all element sizes, except 1xD. | |
4685 | multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm, | |
4686 | SDNode OpNode> { | |
4687 | def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64, | |
4688 | asm, ".8b", "0", | |
4689 | v8i8, v8i8, OpNode>; | |
4690 | def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128, | |
4691 | asm, ".16b", "0", | |
4692 | v16i8, v16i8, OpNode>; | |
4693 | def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64, | |
4694 | asm, ".4h", "0", | |
4695 | v4i16, v4i16, OpNode>; | |
4696 | def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128, | |
4697 | asm, ".8h", "0", | |
4698 | v8i16, v8i16, OpNode>; | |
4699 | def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64, | |
4700 | asm, ".2s", "0", | |
4701 | v2i32, v2i32, OpNode>; | |
4702 | def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128, | |
4703 | asm, ".4s", "0", | |
4704 | v4i32, v4i32, OpNode>; | |
4705 | def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128, | |
4706 | asm, ".2d", "0", | |
4707 | v2i64, v2i64, OpNode>; | |
4708 | } | |
4709 | ||
4710 | // FP Comparisons support only S and D element sizes. | |
4711 | multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc, | |
4712 | string asm, SDNode OpNode> { | |
4713 | ||
4714 | def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64, | |
4715 | asm, ".2s", "0.0", | |
4716 | v2i32, v2f32, OpNode>; | |
4717 | def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128, | |
4718 | asm, ".4s", "0.0", | |
4719 | v4i32, v4f32, OpNode>; | |
4720 | def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128, | |
4721 | asm, ".2d", "0.0", | |
4722 | v2i64, v2f64, OpNode>; | |
4723 | ||
4724 | def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0", | |
4725 | (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>; | |
4726 | def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0", | |
4727 | (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>; | |
4728 | def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0", | |
4729 | (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>; | |
4730 | def : InstAlias<asm # ".2s $Vd, $Vn, #0", | |
4731 | (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>; | |
4732 | def : InstAlias<asm # ".4s $Vd, $Vn, #0", | |
4733 | (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>; | |
4734 | def : InstAlias<asm # ".2d $Vd, $Vn, #0", | |
4735 | (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>; | |
4736 | } | |
4737 | ||
4738 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4739 | class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4740 | RegisterOperand outtype, RegisterOperand intype, | |
4741 | string asm, string VdTy, string VnTy, | |
4742 | list<dag> pattern> | |
4743 | : I<(outs outtype:$Rd), (ins intype:$Rn), asm, | |
4744 | !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>, | |
4745 | Sched<[WriteV]> { | |
4746 | bits<5> Rd; | |
4747 | bits<5> Rn; | |
4748 | let Inst{31} = 0; | |
4749 | let Inst{30} = Q; | |
4750 | let Inst{29} = U; | |
4751 | let Inst{28-24} = 0b01110; | |
4752 | let Inst{23-22} = size; | |
4753 | let Inst{21-17} = 0b10000; | |
4754 | let Inst{16-12} = opcode; | |
4755 | let Inst{11-10} = 0b10; | |
4756 | let Inst{9-5} = Rn; | |
4757 | let Inst{4-0} = Rd; | |
4758 | } | |
4759 | ||
4760 | class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode, | |
4761 | RegisterOperand outtype, RegisterOperand intype, | |
4762 | string asm, string VdTy, string VnTy, | |
4763 | list<dag> pattern> | |
4764 | : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm, | |
4765 | !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>, | |
4766 | Sched<[WriteV]> { | |
4767 | bits<5> Rd; | |
4768 | bits<5> Rn; | |
4769 | let Inst{31} = 0; | |
4770 | let Inst{30} = Q; | |
4771 | let Inst{29} = U; | |
4772 | let Inst{28-24} = 0b01110; | |
4773 | let Inst{23-22} = size; | |
4774 | let Inst{21-17} = 0b10000; | |
4775 | let Inst{16-12} = opcode; | |
4776 | let Inst{11-10} = 0b10; | |
4777 | let Inst{9-5} = Rn; | |
4778 | let Inst{4-0} = Rd; | |
4779 | } | |
4780 | ||
4781 | multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> { | |
4782 | def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64, | |
4783 | asm, ".4s", ".4h", []>; | |
4784 | def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128, | |
4785 | asm#"2", ".4s", ".8h", []>; | |
4786 | def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64, | |
4787 | asm, ".2d", ".2s", []>; | |
4788 | def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128, | |
4789 | asm#"2", ".2d", ".4s", []>; | |
4790 | } | |
4791 | ||
4792 | multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> { | |
4793 | def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128, | |
4794 | asm, ".4h", ".4s", []>; | |
4795 | def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128, | |
4796 | asm#"2", ".8h", ".4s", []>; | |
4797 | def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128, | |
4798 | asm, ".2s", ".2d", []>; | |
4799 | def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128, | |
4800 | asm#"2", ".4s", ".2d", []>; | |
4801 | } | |
4802 | ||
4803 | multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm, | |
4804 | Intrinsic OpNode> { | |
4805 | def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128, | |
4806 | asm, ".2s", ".2d", | |
4807 | [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>; | |
4808 | def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128, | |
4809 | asm#"2", ".4s", ".2d", []>; | |
4810 | ||
4811 | def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))), | |
4812 | (!cast<Instruction>(NAME # "v4f32") | |
4813 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>; | |
4814 | } | |
4815 | ||
4816 | //---------------------------------------------------------------------------- | |
4817 | // AdvSIMD three register different-size vector instructions. | |
4818 | //---------------------------------------------------------------------------- | |
4819 | ||
4820 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4821 | class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode, | |
4822 | RegisterOperand outtype, RegisterOperand intype1, | |
4823 | RegisterOperand intype2, string asm, | |
4824 | string outkind, string inkind1, string inkind2, | |
4825 | list<dag> pattern> | |
4826 | : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm, | |
4827 | "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 # | |
4828 | "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>, | |
4829 | Sched<[WriteV]> { | |
4830 | bits<5> Rd; | |
4831 | bits<5> Rn; | |
4832 | bits<5> Rm; | |
4833 | let Inst{31} = 0; | |
4834 | let Inst{30} = size{0}; | |
4835 | let Inst{29} = U; | |
4836 | let Inst{28-24} = 0b01110; | |
4837 | let Inst{23-22} = size{2-1}; | |
4838 | let Inst{21} = 1; | |
4839 | let Inst{20-16} = Rm; | |
4840 | let Inst{15-12} = opcode; | |
4841 | let Inst{11-10} = 0b00; | |
4842 | let Inst{9-5} = Rn; | |
4843 | let Inst{4-0} = Rd; | |
4844 | } | |
4845 | ||
4846 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
4847 | class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode, | |
4848 | RegisterOperand outtype, RegisterOperand intype1, | |
4849 | RegisterOperand intype2, string asm, | |
4850 | string outkind, string inkind1, string inkind2, | |
4851 | list<dag> pattern> | |
4852 | : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm, | |
4853 | "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 # | |
4854 | "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>, | |
4855 | Sched<[WriteV]> { | |
4856 | bits<5> Rd; | |
4857 | bits<5> Rn; | |
4858 | bits<5> Rm; | |
4859 | let Inst{31} = 0; | |
4860 | let Inst{30} = size{0}; | |
4861 | let Inst{29} = U; | |
4862 | let Inst{28-24} = 0b01110; | |
4863 | let Inst{23-22} = size{2-1}; | |
4864 | let Inst{21} = 1; | |
4865 | let Inst{20-16} = Rm; | |
4866 | let Inst{15-12} = opcode; | |
4867 | let Inst{11-10} = 0b00; | |
4868 | let Inst{9-5} = Rn; | |
4869 | let Inst{4-0} = Rd; | |
4870 | } | |
4871 | ||
4872 | // FIXME: TableGen doesn't know how to deal with expanded types that also | |
4873 | // change the element count (in this case, placing the results in | |
4874 | // the high elements of the result register rather than the low | |
4875 | // elements). Until that's fixed, we can't code-gen those. | |
4876 | multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm, | |
4877 | Intrinsic IntOp> { | |
4878 | def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc, | |
4879 | V64, V128, V128, | |
4880 | asm, ".8b", ".8h", ".8h", | |
4881 | [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>; | |
4882 | def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc, | |
4883 | V128, V128, V128, | |
4884 | asm#"2", ".16b", ".8h", ".8h", | |
4885 | []>; | |
4886 | def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc, | |
4887 | V64, V128, V128, | |
4888 | asm, ".4h", ".4s", ".4s", | |
4889 | [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>; | |
4890 | def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc, | |
4891 | V128, V128, V128, | |
4892 | asm#"2", ".8h", ".4s", ".4s", | |
4893 | []>; | |
4894 | def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc, | |
4895 | V64, V128, V128, | |
4896 | asm, ".2s", ".2d", ".2d", | |
4897 | [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>; | |
4898 | def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc, | |
4899 | V128, V128, V128, | |
4900 | asm#"2", ".4s", ".2d", ".2d", | |
4901 | []>; | |
4902 | ||
4903 | ||
4904 | // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in | |
4905 | // a version attached to an instruction. | |
4906 | def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), | |
4907 | (v8i16 V128:$Rm))), | |
4908 | (!cast<Instruction>(NAME # "v8i16_v16i8") | |
4909 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), | |
4910 | V128:$Rn, V128:$Rm)>; | |
4911 | def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), | |
4912 | (v4i32 V128:$Rm))), | |
4913 | (!cast<Instruction>(NAME # "v4i32_v8i16") | |
4914 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), | |
4915 | V128:$Rn, V128:$Rm)>; | |
4916 | def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), | |
4917 | (v2i64 V128:$Rm))), | |
4918 | (!cast<Instruction>(NAME # "v2i64_v4i32") | |
4919 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), | |
4920 | V128:$Rn, V128:$Rm)>; | |
4921 | } | |
4922 | ||
4923 | multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm, | |
4924 | Intrinsic IntOp> { | |
4925 | def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc, | |
4926 | V128, V64, V64, | |
4927 | asm, ".8h", ".8b", ".8b", | |
4928 | [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
4929 | def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc, | |
4930 | V128, V128, V128, | |
4931 | asm#"2", ".8h", ".16b", ".16b", []>; | |
4932 | let Predicates = [HasCrypto] in { | |
4933 | def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc, | |
4934 | V128, V64, V64, | |
4935 | asm, ".1q", ".1d", ".1d", []>; | |
4936 | def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc, | |
4937 | V128, V128, V128, | |
4938 | asm#"2", ".1q", ".2d", ".2d", []>; | |
4939 | } | |
4940 | ||
4941 | def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)), | |
4942 | (v8i8 (extract_high_v16i8 V128:$Rm)))), | |
4943 | (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>; | |
4944 | } | |
4945 | ||
4946 | multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm, | |
4947 | SDPatternOperator OpNode> { | |
4948 | def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc, | |
4949 | V128, V64, V64, | |
4950 | asm, ".4s", ".4h", ".4h", | |
4951 | [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>; | |
4952 | def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc, | |
4953 | V128, V128, V128, | |
4954 | asm#"2", ".4s", ".8h", ".8h", | |
4955 | [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn), | |
4956 | (extract_high_v8i16 V128:$Rm)))]>; | |
4957 | def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc, | |
4958 | V128, V64, V64, | |
4959 | asm, ".2d", ".2s", ".2s", | |
4960 | [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>; | |
4961 | def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc, | |
4962 | V128, V128, V128, | |
4963 | asm#"2", ".2d", ".4s", ".4s", | |
4964 | [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn), | |
4965 | (extract_high_v4i32 V128:$Rm)))]>; | |
4966 | } | |
4967 | ||
4968 | multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm, | |
4969 | SDPatternOperator OpNode = null_frag> { | |
4970 | def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc, | |
4971 | V128, V64, V64, | |
4972 | asm, ".8h", ".8b", ".8b", | |
4973 | [(set (v8i16 V128:$Rd), | |
4974 | (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>; | |
4975 | def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc, | |
4976 | V128, V128, V128, | |
4977 | asm#"2", ".8h", ".16b", ".16b", | |
4978 | [(set (v8i16 V128:$Rd), | |
4979 | (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn), | |
4980 | (extract_high_v16i8 V128:$Rm)))))]>; | |
4981 | def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc, | |
4982 | V128, V64, V64, | |
4983 | asm, ".4s", ".4h", ".4h", | |
4984 | [(set (v4i32 V128:$Rd), | |
4985 | (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>; | |
4986 | def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc, | |
4987 | V128, V128, V128, | |
4988 | asm#"2", ".4s", ".8h", ".8h", | |
4989 | [(set (v4i32 V128:$Rd), | |
4990 | (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn), | |
4991 | (extract_high_v8i16 V128:$Rm)))))]>; | |
4992 | def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc, | |
4993 | V128, V64, V64, | |
4994 | asm, ".2d", ".2s", ".2s", | |
4995 | [(set (v2i64 V128:$Rd), | |
4996 | (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>; | |
4997 | def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc, | |
4998 | V128, V128, V128, | |
4999 | asm#"2", ".2d", ".4s", ".4s", | |
5000 | [(set (v2i64 V128:$Rd), | |
5001 | (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn), | |
5002 | (extract_high_v4i32 V128:$Rm)))))]>; | |
5003 | } | |
5004 | ||
5005 | multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc, | |
5006 | string asm, | |
5007 | SDPatternOperator OpNode> { | |
5008 | def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc, | |
5009 | V128, V64, V64, | |
5010 | asm, ".8h", ".8b", ".8b", | |
5011 | [(set (v8i16 V128:$dst), | |
5012 | (add (v8i16 V128:$Rd), | |
5013 | (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>; | |
5014 | def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc, | |
5015 | V128, V128, V128, | |
5016 | asm#"2", ".8h", ".16b", ".16b", | |
5017 | [(set (v8i16 V128:$dst), | |
5018 | (add (v8i16 V128:$Rd), | |
5019 | (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn), | |
5020 | (extract_high_v16i8 V128:$Rm))))))]>; | |
5021 | def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc, | |
5022 | V128, V64, V64, | |
5023 | asm, ".4s", ".4h", ".4h", | |
5024 | [(set (v4i32 V128:$dst), | |
5025 | (add (v4i32 V128:$Rd), | |
5026 | (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>; | |
5027 | def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc, | |
5028 | V128, V128, V128, | |
5029 | asm#"2", ".4s", ".8h", ".8h", | |
5030 | [(set (v4i32 V128:$dst), | |
5031 | (add (v4i32 V128:$Rd), | |
5032 | (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn), | |
5033 | (extract_high_v8i16 V128:$Rm))))))]>; | |
5034 | def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc, | |
5035 | V128, V64, V64, | |
5036 | asm, ".2d", ".2s", ".2s", | |
5037 | [(set (v2i64 V128:$dst), | |
5038 | (add (v2i64 V128:$Rd), | |
5039 | (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>; | |
5040 | def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc, | |
5041 | V128, V128, V128, | |
5042 | asm#"2", ".2d", ".4s", ".4s", | |
5043 | [(set (v2i64 V128:$dst), | |
5044 | (add (v2i64 V128:$Rd), | |
5045 | (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn), | |
5046 | (extract_high_v4i32 V128:$Rm))))))]>; | |
5047 | } | |
5048 | ||
5049 | multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm, | |
5050 | SDPatternOperator OpNode = null_frag> { | |
5051 | def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc, | |
5052 | V128, V64, V64, | |
5053 | asm, ".8h", ".8b", ".8b", | |
5054 | [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
5055 | def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc, | |
5056 | V128, V128, V128, | |
5057 | asm#"2", ".8h", ".16b", ".16b", | |
5058 | [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn), | |
5059 | (extract_high_v16i8 V128:$Rm)))]>; | |
5060 | def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc, | |
5061 | V128, V64, V64, | |
5062 | asm, ".4s", ".4h", ".4h", | |
5063 | [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>; | |
5064 | def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc, | |
5065 | V128, V128, V128, | |
5066 | asm#"2", ".4s", ".8h", ".8h", | |
5067 | [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn), | |
5068 | (extract_high_v8i16 V128:$Rm)))]>; | |
5069 | def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc, | |
5070 | V128, V64, V64, | |
5071 | asm, ".2d", ".2s", ".2s", | |
5072 | [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>; | |
5073 | def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc, | |
5074 | V128, V128, V128, | |
5075 | asm#"2", ".2d", ".4s", ".4s", | |
5076 | [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn), | |
5077 | (extract_high_v4i32 V128:$Rm)))]>; | |
5078 | } | |
5079 | ||
5080 | multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc, | |
5081 | string asm, | |
5082 | SDPatternOperator OpNode> { | |
5083 | def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc, | |
5084 | V128, V64, V64, | |
5085 | asm, ".8h", ".8b", ".8b", | |
5086 | [(set (v8i16 V128:$dst), | |
5087 | (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>; | |
5088 | def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc, | |
5089 | V128, V128, V128, | |
5090 | asm#"2", ".8h", ".16b", ".16b", | |
5091 | [(set (v8i16 V128:$dst), | |
5092 | (OpNode (v8i16 V128:$Rd), | |
5093 | (extract_high_v16i8 V128:$Rn), | |
5094 | (extract_high_v16i8 V128:$Rm)))]>; | |
5095 | def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc, | |
5096 | V128, V64, V64, | |
5097 | asm, ".4s", ".4h", ".4h", | |
5098 | [(set (v4i32 V128:$dst), | |
5099 | (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>; | |
5100 | def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc, | |
5101 | V128, V128, V128, | |
5102 | asm#"2", ".4s", ".8h", ".8h", | |
5103 | [(set (v4i32 V128:$dst), | |
5104 | (OpNode (v4i32 V128:$Rd), | |
5105 | (extract_high_v8i16 V128:$Rn), | |
5106 | (extract_high_v8i16 V128:$Rm)))]>; | |
5107 | def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc, | |
5108 | V128, V64, V64, | |
5109 | asm, ".2d", ".2s", ".2s", | |
5110 | [(set (v2i64 V128:$dst), | |
5111 | (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>; | |
5112 | def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc, | |
5113 | V128, V128, V128, | |
5114 | asm#"2", ".2d", ".4s", ".4s", | |
5115 | [(set (v2i64 V128:$dst), | |
5116 | (OpNode (v2i64 V128:$Rd), | |
5117 | (extract_high_v4i32 V128:$Rn), | |
5118 | (extract_high_v4i32 V128:$Rm)))]>; | |
5119 | } | |
5120 | ||
5121 | multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm, | |
5122 | SDPatternOperator Accum> { | |
5123 | def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc, | |
5124 | V128, V64, V64, | |
5125 | asm, ".4s", ".4h", ".4h", | |
5126 | [(set (v4i32 V128:$dst), | |
5127 | (Accum (v4i32 V128:$Rd), | |
5128 | (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn), | |
5129 | (v4i16 V64:$Rm)))))]>; | |
5130 | def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc, | |
5131 | V128, V128, V128, | |
5132 | asm#"2", ".4s", ".8h", ".8h", | |
5133 | [(set (v4i32 V128:$dst), | |
5134 | (Accum (v4i32 V128:$Rd), | |
5135 | (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn), | |
5136 | (extract_high_v8i16 V128:$Rm)))))]>; | |
5137 | def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc, | |
5138 | V128, V64, V64, | |
5139 | asm, ".2d", ".2s", ".2s", | |
5140 | [(set (v2i64 V128:$dst), | |
5141 | (Accum (v2i64 V128:$Rd), | |
5142 | (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn), | |
5143 | (v2i32 V64:$Rm)))))]>; | |
5144 | def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc, | |
5145 | V128, V128, V128, | |
5146 | asm#"2", ".2d", ".4s", ".4s", | |
5147 | [(set (v2i64 V128:$dst), | |
5148 | (Accum (v2i64 V128:$Rd), | |
5149 | (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn), | |
5150 | (extract_high_v4i32 V128:$Rm)))))]>; | |
5151 | } | |
5152 | ||
5153 | multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm, | |
5154 | SDPatternOperator OpNode> { | |
5155 | def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc, | |
5156 | V128, V128, V64, | |
5157 | asm, ".8h", ".8h", ".8b", | |
5158 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>; | |
5159 | def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc, | |
5160 | V128, V128, V128, | |
5161 | asm#"2", ".8h", ".8h", ".16b", | |
5162 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), | |
5163 | (extract_high_v16i8 V128:$Rm)))]>; | |
5164 | def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc, | |
5165 | V128, V128, V64, | |
5166 | asm, ".4s", ".4s", ".4h", | |
5167 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>; | |
5168 | def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc, | |
5169 | V128, V128, V128, | |
5170 | asm#"2", ".4s", ".4s", ".8h", | |
5171 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), | |
5172 | (extract_high_v8i16 V128:$Rm)))]>; | |
5173 | def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc, | |
5174 | V128, V128, V64, | |
5175 | asm, ".2d", ".2d", ".2s", | |
5176 | [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>; | |
5177 | def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc, | |
5178 | V128, V128, V128, | |
5179 | asm#"2", ".2d", ".2d", ".4s", | |
5180 | [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), | |
5181 | (extract_high_v4i32 V128:$Rm)))]>; | |
5182 | } | |
5183 | ||
5184 | //---------------------------------------------------------------------------- | |
5185 | // AdvSIMD bitwise extract from vector | |
5186 | //---------------------------------------------------------------------------- | |
5187 | ||
5188 | class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty, | |
5189 | string asm, string kind> | |
5190 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm, | |
5191 | "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" # | |
5192 | "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "", | |
5193 | [(set (vty regtype:$Rd), | |
5194 | (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>, | |
5195 | Sched<[WriteV]> { | |
5196 | bits<5> Rd; | |
5197 | bits<5> Rn; | |
5198 | bits<5> Rm; | |
5199 | bits<4> imm; | |
5200 | let Inst{31} = 0; | |
5201 | let Inst{30} = size; | |
5202 | let Inst{29-21} = 0b101110000; | |
5203 | let Inst{20-16} = Rm; | |
5204 | let Inst{15} = 0; | |
5205 | let Inst{14-11} = imm; | |
5206 | let Inst{10} = 0; | |
5207 | let Inst{9-5} = Rn; | |
5208 | let Inst{4-0} = Rd; | |
5209 | } | |
5210 | ||
5211 | ||
5212 | multiclass SIMDBitwiseExtract<string asm> { | |
5213 | def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> { | |
5214 | let imm{3} = 0; | |
5215 | } | |
5216 | def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">; | |
5217 | } | |
5218 | ||
5219 | //---------------------------------------------------------------------------- | |
5220 | // AdvSIMD zip vector | |
5221 | //---------------------------------------------------------------------------- | |
5222 | ||
5223 | class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype, | |
5224 | string asm, string kind, SDNode OpNode, ValueType valty> | |
5225 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm, | |
5226 | "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # | |
5227 | "|" # kind # "\t$Rd, $Rn, $Rm}", "", | |
5228 | [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>, | |
5229 | Sched<[WriteV]> { | |
5230 | bits<5> Rd; | |
5231 | bits<5> Rn; | |
5232 | bits<5> Rm; | |
5233 | let Inst{31} = 0; | |
5234 | let Inst{30} = size{0}; | |
5235 | let Inst{29-24} = 0b001110; | |
5236 | let Inst{23-22} = size{2-1}; | |
5237 | let Inst{21} = 0; | |
5238 | let Inst{20-16} = Rm; | |
5239 | let Inst{15} = 0; | |
5240 | let Inst{14-12} = opc; | |
5241 | let Inst{11-10} = 0b10; | |
5242 | let Inst{9-5} = Rn; | |
5243 | let Inst{4-0} = Rd; | |
5244 | } | |
5245 | ||
5246 | multiclass SIMDZipVector<bits<3>opc, string asm, | |
5247 | SDNode OpNode> { | |
5248 | def v8i8 : BaseSIMDZipVector<0b000, opc, V64, | |
5249 | asm, ".8b", OpNode, v8i8>; | |
5250 | def v16i8 : BaseSIMDZipVector<0b001, opc, V128, | |
5251 | asm, ".16b", OpNode, v16i8>; | |
5252 | def v4i16 : BaseSIMDZipVector<0b010, opc, V64, | |
5253 | asm, ".4h", OpNode, v4i16>; | |
5254 | def v8i16 : BaseSIMDZipVector<0b011, opc, V128, | |
5255 | asm, ".8h", OpNode, v8i16>; | |
5256 | def v2i32 : BaseSIMDZipVector<0b100, opc, V64, | |
5257 | asm, ".2s", OpNode, v2i32>; | |
5258 | def v4i32 : BaseSIMDZipVector<0b101, opc, V128, | |
5259 | asm, ".4s", OpNode, v4i32>; | |
5260 | def v2i64 : BaseSIMDZipVector<0b111, opc, V128, | |
5261 | asm, ".2d", OpNode, v2i64>; | |
5262 | ||
5263 | def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)), | |
5264 | (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>; | |
5265 | def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)), | |
5266 | (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>; | |
5267 | def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)), | |
5268 | (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>; | |
5269 | def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)), | |
5270 | (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>; | |
5271 | def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)), | |
5272 | (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>; | |
5273 | } | |
5274 | ||
5275 | //---------------------------------------------------------------------------- | |
5276 | // AdvSIMD three register scalar instructions | |
5277 | //---------------------------------------------------------------------------- | |
5278 | ||
5279 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
5280 | class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode, | |
5281 | RegisterClass regtype, string asm, | |
5282 | list<dag> pattern> | |
5283 | : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm, | |
5284 | "\t$Rd, $Rn, $Rm", "", pattern>, | |
5285 | Sched<[WriteV]> { | |
5286 | bits<5> Rd; | |
5287 | bits<5> Rn; | |
5288 | bits<5> Rm; | |
5289 | let Inst{31-30} = 0b01; | |
5290 | let Inst{29} = U; | |
5291 | let Inst{28-24} = 0b11110; | |
5292 | let Inst{23-22} = size; | |
5293 | let Inst{21} = 1; | |
5294 | let Inst{20-16} = Rm; | |
5295 | let Inst{15-11} = opcode; | |
5296 | let Inst{10} = 1; | |
5297 | let Inst{9-5} = Rn; | |
5298 | let Inst{4-0} = Rd; | |
5299 | } | |
5300 | ||
5301 | multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm, | |
5302 | SDPatternOperator OpNode> { | |
5303 | def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm, | |
5304 | [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>; | |
5305 | } | |
5306 | ||
5307 | multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm, | |
5308 | SDPatternOperator OpNode> { | |
5309 | def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm, | |
5310 | [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>; | |
5311 | def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>; | |
5312 | def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>; | |
5313 | def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>; | |
5314 | ||
5315 | def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))), | |
5316 | (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>; | |
5317 | def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))), | |
5318 | (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>; | |
5319 | } | |
5320 | ||
5321 | multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm, | |
5322 | SDPatternOperator OpNode> { | |
5323 | def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, | |
5324 | [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>; | |
5325 | def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>; | |
5326 | } | |
5327 | ||
5328 | multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm, | |
5329 | SDPatternOperator OpNode = null_frag> { | |
5330 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
5331 | def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm, | |
5332 | [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>; | |
5333 | def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm, | |
5334 | [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>; | |
5335 | } | |
5336 | ||
5337 | def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))), | |
5338 | (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>; | |
5339 | } | |
5340 | ||
5341 | multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm, | |
5342 | SDPatternOperator OpNode = null_frag> { | |
5343 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
5344 | def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm, | |
5345 | [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>; | |
5346 | def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm, | |
5347 | [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>; | |
5348 | } | |
5349 | ||
5350 | def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))), | |
5351 | (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>; | |
5352 | } | |
5353 | ||
5354 | class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode, | |
5355 | dag oops, dag iops, string asm, string cstr, list<dag> pat> | |
5356 | : I<oops, iops, asm, | |
5357 | "\t$Rd, $Rn, $Rm", cstr, pat>, | |
5358 | Sched<[WriteV]> { | |
5359 | bits<5> Rd; | |
5360 | bits<5> Rn; | |
5361 | bits<5> Rm; | |
5362 | let Inst{31-30} = 0b01; | |
5363 | let Inst{29} = U; | |
5364 | let Inst{28-24} = 0b11110; | |
5365 | let Inst{23-22} = size; | |
5366 | let Inst{21} = 1; | |
5367 | let Inst{20-16} = Rm; | |
5368 | let Inst{15-11} = opcode; | |
5369 | let Inst{10} = 0; | |
5370 | let Inst{9-5} = Rn; | |
5371 | let Inst{4-0} = Rd; | |
5372 | } | |
5373 | ||
5374 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5375 | multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm, | |
5376 | SDPatternOperator OpNode = null_frag> { | |
5377 | def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc, | |
5378 | (outs FPR32:$Rd), | |
5379 | (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>; | |
5380 | def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc, | |
5381 | (outs FPR64:$Rd), | |
5382 | (ins FPR32:$Rn, FPR32:$Rm), asm, "", | |
5383 | [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>; | |
5384 | } | |
5385 | ||
5386 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5387 | multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm, | |
5388 | SDPatternOperator OpNode = null_frag> { | |
5389 | def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc, | |
5390 | (outs FPR32:$dst), | |
5391 | (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm), | |
5392 | asm, "$Rd = $dst", []>; | |
5393 | def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc, | |
5394 | (outs FPR64:$dst), | |
5395 | (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm), | |
5396 | asm, "$Rd = $dst", | |
5397 | [(set (i64 FPR64:$dst), | |
5398 | (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>; | |
5399 | } | |
5400 | ||
5401 | //---------------------------------------------------------------------------- | |
5402 | // AdvSIMD two register scalar instructions | |
5403 | //---------------------------------------------------------------------------- | |
5404 | ||
5405 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5406 | class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode, | |
5407 | RegisterClass regtype, RegisterClass regtype2, | |
5408 | string asm, list<dag> pat> | |
5409 | : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm, | |
5410 | "\t$Rd, $Rn", "", pat>, | |
5411 | Sched<[WriteV]> { | |
5412 | bits<5> Rd; | |
5413 | bits<5> Rn; | |
5414 | let Inst{31-30} = 0b01; | |
5415 | let Inst{29} = U; | |
5416 | let Inst{28-24} = 0b11110; | |
5417 | let Inst{23-22} = size; | |
5418 | let Inst{21-17} = 0b10000; | |
5419 | let Inst{16-12} = opcode; | |
5420 | let Inst{11-10} = 0b10; | |
5421 | let Inst{9-5} = Rn; | |
5422 | let Inst{4-0} = Rd; | |
5423 | } | |
5424 | ||
5425 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5426 | class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode, | |
5427 | RegisterClass regtype, RegisterClass regtype2, | |
5428 | string asm, list<dag> pat> | |
5429 | : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm, | |
5430 | "\t$Rd, $Rn", "$Rd = $dst", pat>, | |
5431 | Sched<[WriteV]> { | |
5432 | bits<5> Rd; | |
5433 | bits<5> Rn; | |
5434 | let Inst{31-30} = 0b01; | |
5435 | let Inst{29} = U; | |
5436 | let Inst{28-24} = 0b11110; | |
5437 | let Inst{23-22} = size; | |
5438 | let Inst{21-17} = 0b10000; | |
5439 | let Inst{16-12} = opcode; | |
5440 | let Inst{11-10} = 0b10; | |
5441 | let Inst{9-5} = Rn; | |
5442 | let Inst{4-0} = Rd; | |
5443 | } | |
5444 | ||
5445 | ||
5446 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5447 | class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode, | |
5448 | RegisterClass regtype, string asm, string zero> | |
5449 | : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, | |
5450 | "\t$Rd, $Rn, #" # zero, "", []>, | |
5451 | Sched<[WriteV]> { | |
5452 | bits<5> Rd; | |
5453 | bits<5> Rn; | |
5454 | let Inst{31-30} = 0b01; | |
5455 | let Inst{29} = U; | |
5456 | let Inst{28-24} = 0b11110; | |
5457 | let Inst{23-22} = size; | |
5458 | let Inst{21-17} = 0b10000; | |
5459 | let Inst{16-12} = opcode; | |
5460 | let Inst{11-10} = 0b10; | |
5461 | let Inst{9-5} = Rn; | |
5462 | let Inst{4-0} = Rd; | |
5463 | } | |
5464 | ||
5465 | class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm> | |
5466 | : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "", | |
5467 | [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>, | |
5468 | Sched<[WriteV]> { | |
5469 | bits<5> Rd; | |
5470 | bits<5> Rn; | |
5471 | let Inst{31-17} = 0b011111100110000; | |
5472 | let Inst{16-12} = opcode; | |
5473 | let Inst{11-10} = 0b10; | |
5474 | let Inst{9-5} = Rn; | |
5475 | let Inst{4-0} = Rd; | |
5476 | } | |
5477 | ||
5478 | multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm, | |
5479 | SDPatternOperator OpNode> { | |
5480 | def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">; | |
5481 | ||
5482 | def : Pat<(v1i64 (OpNode FPR64:$Rn)), | |
5483 | (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>; | |
5484 | } | |
5485 | ||
5486 | multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm, | |
5487 | SDPatternOperator OpNode> { | |
5488 | def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">; | |
5489 | def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">; | |
5490 | ||
5491 | def : InstAlias<asm # " $Rd, $Rn, #0", | |
5492 | (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>; | |
5493 | def : InstAlias<asm # " $Rd, $Rn, #0", | |
5494 | (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>; | |
5495 | ||
5496 | def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))), | |
5497 | (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>; | |
5498 | } | |
5499 | ||
5500 | multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm, | |
5501 | SDPatternOperator OpNode = null_frag> { | |
5502 | def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm, | |
5503 | [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>; | |
5504 | ||
5505 | def : Pat<(i64 (OpNode (i64 FPR64:$Rn))), | |
5506 | (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>; | |
5507 | } | |
5508 | ||
5509 | multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> { | |
5510 | def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>; | |
5511 | def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>; | |
5512 | } | |
5513 | ||
5514 | multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm, | |
5515 | SDPatternOperator OpNode> { | |
5516 | def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm, | |
5517 | [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>; | |
5518 | def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm, | |
5519 | [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>; | |
5520 | } | |
5521 | ||
5522 | multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm, | |
5523 | SDPatternOperator OpNode = null_frag> { | |
5524 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
5525 | def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm, | |
5526 | [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>; | |
5527 | def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm, | |
5528 | [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>; | |
5529 | def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>; | |
5530 | def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>; | |
5531 | } | |
5532 | ||
5533 | def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))), | |
5534 | (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>; | |
5535 | } | |
5536 | ||
5537 | multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm, | |
5538 | Intrinsic OpNode> { | |
5539 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
5540 | def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm, | |
5541 | [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>; | |
5542 | def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm, | |
5543 | [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>; | |
5544 | def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>; | |
5545 | def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>; | |
5546 | } | |
5547 | ||
5548 | def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))), | |
5549 | (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>; | |
5550 | } | |
5551 | ||
5552 | ||
5553 | ||
5554 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5555 | multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm, | |
5556 | SDPatternOperator OpNode = null_frag> { | |
5557 | def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm, | |
5558 | [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>; | |
5559 | def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>; | |
5560 | def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>; | |
5561 | } | |
5562 | ||
5563 | //---------------------------------------------------------------------------- | |
5564 | // AdvSIMD scalar pairwise instructions | |
5565 | //---------------------------------------------------------------------------- | |
5566 | ||
5567 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5568 | class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode, | |
5569 | RegisterOperand regtype, RegisterOperand vectype, | |
5570 | string asm, string kind> | |
5571 | : I<(outs regtype:$Rd), (ins vectype:$Rn), asm, | |
5572 | "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>, | |
5573 | Sched<[WriteV]> { | |
5574 | bits<5> Rd; | |
5575 | bits<5> Rn; | |
5576 | let Inst{31-30} = 0b01; | |
5577 | let Inst{29} = U; | |
5578 | let Inst{28-24} = 0b11110; | |
5579 | let Inst{23-22} = size; | |
5580 | let Inst{21-17} = 0b11000; | |
5581 | let Inst{16-12} = opcode; | |
5582 | let Inst{11-10} = 0b10; | |
5583 | let Inst{9-5} = Rn; | |
5584 | let Inst{4-0} = Rd; | |
5585 | } | |
5586 | ||
5587 | multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> { | |
5588 | def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128, | |
5589 | asm, ".2d">; | |
5590 | } | |
5591 | ||
5592 | multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> { | |
5593 | def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64, | |
5594 | asm, ".2s">; | |
5595 | def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128, | |
5596 | asm, ".2d">; | |
5597 | } | |
5598 | ||
5599 | //---------------------------------------------------------------------------- | |
5600 | // AdvSIMD across lanes instructions | |
5601 | //---------------------------------------------------------------------------- | |
5602 | ||
5603 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
5604 | class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode, | |
5605 | RegisterClass regtype, RegisterOperand vectype, | |
5606 | string asm, string kind, list<dag> pattern> | |
5607 | : I<(outs regtype:$Rd), (ins vectype:$Rn), asm, | |
5608 | "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>, | |
5609 | Sched<[WriteV]> { | |
5610 | bits<5> Rd; | |
5611 | bits<5> Rn; | |
5612 | let Inst{31} = 0; | |
5613 | let Inst{30} = Q; | |
5614 | let Inst{29} = U; | |
5615 | let Inst{28-24} = 0b01110; | |
5616 | let Inst{23-22} = size; | |
5617 | let Inst{21-17} = 0b11000; | |
5618 | let Inst{16-12} = opcode; | |
5619 | let Inst{11-10} = 0b10; | |
5620 | let Inst{9-5} = Rn; | |
5621 | let Inst{4-0} = Rd; | |
5622 | } | |
5623 | ||
5624 | multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode, | |
5625 | string asm> { | |
5626 | def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64, | |
5627 | asm, ".8b", []>; | |
5628 | def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128, | |
5629 | asm, ".16b", []>; | |
5630 | def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64, | |
5631 | asm, ".4h", []>; | |
5632 | def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128, | |
5633 | asm, ".8h", []>; | |
5634 | def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128, | |
5635 | asm, ".4s", []>; | |
5636 | } | |
5637 | ||
5638 | multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> { | |
5639 | def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64, | |
5640 | asm, ".8b", []>; | |
5641 | def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128, | |
5642 | asm, ".16b", []>; | |
5643 | def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64, | |
5644 | asm, ".4h", []>; | |
5645 | def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128, | |
5646 | asm, ".8h", []>; | |
5647 | def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128, | |
5648 | asm, ".4s", []>; | |
5649 | } | |
5650 | ||
5651 | multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm, | |
5652 | Intrinsic intOp> { | |
5653 | def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128, | |
5654 | asm, ".4s", | |
5655 | [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>; | |
5656 | } | |
5657 | ||
5658 | //---------------------------------------------------------------------------- | |
5659 | // AdvSIMD INS/DUP instructions | |
5660 | //---------------------------------------------------------------------------- | |
5661 | ||
5662 | // FIXME: There has got to be a better way to factor these. ugh. | |
5663 | ||
5664 | class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm, | |
5665 | string operands, string constraints, list<dag> pattern> | |
5666 | : I<outs, ins, asm, operands, constraints, pattern>, | |
5667 | Sched<[WriteV]> { | |
5668 | bits<5> Rd; | |
5669 | bits<5> Rn; | |
5670 | let Inst{31} = 0; | |
5671 | let Inst{30} = Q; | |
5672 | let Inst{29} = op; | |
5673 | let Inst{28-21} = 0b01110000; | |
5674 | let Inst{15} = 0; | |
5675 | let Inst{10} = 1; | |
5676 | let Inst{9-5} = Rn; | |
5677 | let Inst{4-0} = Rd; | |
5678 | } | |
5679 | ||
5680 | class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype, | |
5681 | RegisterOperand vecreg, RegisterClass regtype> | |
5682 | : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup", | |
5683 | "{\t$Rd" # size # ", $Rn" # | |
5684 | "|" # size # "\t$Rd, $Rn}", "", | |
5685 | [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> { | |
5686 | let Inst{20-16} = imm5; | |
5687 | let Inst{14-11} = 0b0001; | |
5688 | } | |
5689 | ||
5690 | class SIMDDupFromElement<bit Q, string dstkind, string srckind, | |
5691 | ValueType vectype, ValueType insreg, | |
5692 | RegisterOperand vecreg, Operand idxtype, | |
5693 | ValueType elttype, SDNode OpNode> | |
5694 | : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup", | |
5695 | "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" # | |
5696 | "|" # dstkind # "\t$Rd, $Rn$idx}", "", | |
5697 | [(set (vectype vecreg:$Rd), | |
5698 | (OpNode (insreg V128:$Rn), idxtype:$idx))]> { | |
5699 | let Inst{14-11} = 0b0000; | |
5700 | } | |
5701 | ||
5702 | class SIMDDup64FromElement | |
5703 | : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128, | |
5704 | VectorIndexD, i64, AArch64duplane64> { | |
5705 | bits<1> idx; | |
5706 | let Inst{20} = idx; | |
5707 | let Inst{19-16} = 0b1000; | |
5708 | } | |
5709 | ||
5710 | class SIMDDup32FromElement<bit Q, string size, ValueType vectype, | |
5711 | RegisterOperand vecreg> | |
5712 | : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg, | |
5713 | VectorIndexS, i64, AArch64duplane32> { | |
5714 | bits<2> idx; | |
5715 | let Inst{20-19} = idx; | |
5716 | let Inst{18-16} = 0b100; | |
5717 | } | |
5718 | ||
5719 | class SIMDDup16FromElement<bit Q, string size, ValueType vectype, | |
5720 | RegisterOperand vecreg> | |
5721 | : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg, | |
5722 | VectorIndexH, i64, AArch64duplane16> { | |
5723 | bits<3> idx; | |
5724 | let Inst{20-18} = idx; | |
5725 | let Inst{17-16} = 0b10; | |
5726 | } | |
5727 | ||
5728 | class SIMDDup8FromElement<bit Q, string size, ValueType vectype, | |
5729 | RegisterOperand vecreg> | |
5730 | : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg, | |
5731 | VectorIndexB, i64, AArch64duplane8> { | |
5732 | bits<4> idx; | |
5733 | let Inst{20-17} = idx; | |
5734 | let Inst{16} = 1; | |
5735 | } | |
5736 | ||
5737 | class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype, | |
5738 | Operand idxtype, string asm, list<dag> pattern> | |
5739 | : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm, | |
5740 | "{\t$Rd, $Rn" # size # "$idx" # | |
5741 | "|" # size # "\t$Rd, $Rn$idx}", "", pattern> { | |
5742 | let Inst{14-11} = imm4; | |
5743 | } | |
5744 | ||
5745 | class SIMDSMov<bit Q, string size, RegisterClass regtype, | |
5746 | Operand idxtype> | |
5747 | : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>; | |
5748 | class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype, | |
5749 | Operand idxtype> | |
5750 | : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov", | |
5751 | [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>; | |
5752 | ||
5753 | class SIMDMovAlias<string asm, string size, Instruction inst, | |
5754 | RegisterClass regtype, Operand idxtype> | |
5755 | : InstAlias<asm#"{\t$dst, $src"#size#"$idx" # | |
5756 | "|" # size # "\t$dst, $src$idx}", | |
5757 | (inst regtype:$dst, V128:$src, idxtype:$idx)>; | |
5758 | ||
5759 | multiclass SMov { | |
5760 | def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> { | |
5761 | bits<4> idx; | |
5762 | let Inst{20-17} = idx; | |
5763 | let Inst{16} = 1; | |
5764 | } | |
5765 | def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> { | |
5766 | bits<4> idx; | |
5767 | let Inst{20-17} = idx; | |
5768 | let Inst{16} = 1; | |
5769 | } | |
5770 | def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> { | |
5771 | bits<3> idx; | |
5772 | let Inst{20-18} = idx; | |
5773 | let Inst{17-16} = 0b10; | |
5774 | } | |
5775 | def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> { | |
5776 | bits<3> idx; | |
5777 | let Inst{20-18} = idx; | |
5778 | let Inst{17-16} = 0b10; | |
5779 | } | |
5780 | def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> { | |
5781 | bits<2> idx; | |
5782 | let Inst{20-19} = idx; | |
5783 | let Inst{18-16} = 0b100; | |
5784 | } | |
5785 | } | |
5786 | ||
5787 | multiclass UMov { | |
5788 | def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> { | |
5789 | bits<4> idx; | |
5790 | let Inst{20-17} = idx; | |
5791 | let Inst{16} = 1; | |
5792 | } | |
5793 | def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> { | |
5794 | bits<3> idx; | |
5795 | let Inst{20-18} = idx; | |
5796 | let Inst{17-16} = 0b10; | |
5797 | } | |
5798 | def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> { | |
5799 | bits<2> idx; | |
5800 | let Inst{20-19} = idx; | |
5801 | let Inst{18-16} = 0b100; | |
5802 | } | |
5803 | def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> { | |
5804 | bits<1> idx; | |
5805 | let Inst{20} = idx; | |
5806 | let Inst{19-16} = 0b1000; | |
5807 | } | |
5808 | def : SIMDMovAlias<"mov", ".s", | |
5809 | !cast<Instruction>(NAME#"vi32"), | |
5810 | GPR32, VectorIndexS>; | |
5811 | def : SIMDMovAlias<"mov", ".d", | |
5812 | !cast<Instruction>(NAME#"vi64"), | |
5813 | GPR64, VectorIndexD>; | |
5814 | } | |
5815 | ||
5816 | class SIMDInsFromMain<string size, ValueType vectype, | |
5817 | RegisterClass regtype, Operand idxtype> | |
5818 | : BaseSIMDInsDup<1, 0, (outs V128:$dst), | |
5819 | (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins", | |
5820 | "{\t$Rd" # size # "$idx, $Rn" # | |
5821 | "|" # size # "\t$Rd$idx, $Rn}", | |
5822 | "$Rd = $dst", | |
5823 | [(set V128:$dst, | |
5824 | (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> { | |
5825 | let Inst{14-11} = 0b0011; | |
5826 | } | |
5827 | ||
5828 | class SIMDInsFromElement<string size, ValueType vectype, | |
5829 | ValueType elttype, Operand idxtype> | |
5830 | : BaseSIMDInsDup<1, 1, (outs V128:$dst), | |
5831 | (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins", | |
5832 | "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" # | |
5833 | "|" # size # "\t$Rd$idx, $Rn$idx2}", | |
5834 | "$Rd = $dst", | |
5835 | [(set V128:$dst, | |
5836 | (vector_insert | |
5837 | (vectype V128:$Rd), | |
5838 | (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)), | |
5839 | idxtype:$idx))]>; | |
5840 | ||
5841 | class SIMDInsMainMovAlias<string size, Instruction inst, | |
5842 | RegisterClass regtype, Operand idxtype> | |
5843 | : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # | |
5844 | "|" # size #"\t$dst$idx, $src}", | |
5845 | (inst V128:$dst, idxtype:$idx, regtype:$src)>; | |
5846 | class SIMDInsElementMovAlias<string size, Instruction inst, | |
5847 | Operand idxtype> | |
5848 | : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" # | |
5849 | # "|" # size #" $dst$idx, $src$idx2}", | |
5850 | (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>; | |
5851 | ||
5852 | ||
5853 | multiclass SIMDIns { | |
5854 | def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> { | |
5855 | bits<4> idx; | |
5856 | let Inst{20-17} = idx; | |
5857 | let Inst{16} = 1; | |
5858 | } | |
5859 | def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> { | |
5860 | bits<3> idx; | |
5861 | let Inst{20-18} = idx; | |
5862 | let Inst{17-16} = 0b10; | |
5863 | } | |
5864 | def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> { | |
5865 | bits<2> idx; | |
5866 | let Inst{20-19} = idx; | |
5867 | let Inst{18-16} = 0b100; | |
5868 | } | |
5869 | def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> { | |
5870 | bits<1> idx; | |
5871 | let Inst{20} = idx; | |
5872 | let Inst{19-16} = 0b1000; | |
5873 | } | |
5874 | ||
5875 | def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> { | |
5876 | bits<4> idx; | |
5877 | bits<4> idx2; | |
5878 | let Inst{20-17} = idx; | |
5879 | let Inst{16} = 1; | |
5880 | let Inst{14-11} = idx2; | |
5881 | } | |
5882 | def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> { | |
5883 | bits<3> idx; | |
5884 | bits<3> idx2; | |
5885 | let Inst{20-18} = idx; | |
5886 | let Inst{17-16} = 0b10; | |
5887 | let Inst{14-12} = idx2; | |
5888 | let Inst{11} = 0; | |
5889 | } | |
5890 | def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> { | |
5891 | bits<2> idx; | |
5892 | bits<2> idx2; | |
5893 | let Inst{20-19} = idx; | |
5894 | let Inst{18-16} = 0b100; | |
5895 | let Inst{14-13} = idx2; | |
5896 | let Inst{12-11} = 0; | |
5897 | } | |
5898 | def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> { | |
5899 | bits<1> idx; | |
5900 | bits<1> idx2; | |
5901 | let Inst{20} = idx; | |
5902 | let Inst{19-16} = 0b1000; | |
5903 | let Inst{14} = idx2; | |
5904 | let Inst{13-11} = 0; | |
5905 | } | |
5906 | ||
5907 | // For all forms of the INS instruction, the "mov" mnemonic is the | |
5908 | // preferred alias. Why they didn't just call the instruction "mov" in | |
5909 | // the first place is a very good question indeed... | |
5910 | def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"), | |
5911 | GPR32, VectorIndexB>; | |
5912 | def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"), | |
5913 | GPR32, VectorIndexH>; | |
5914 | def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"), | |
5915 | GPR32, VectorIndexS>; | |
5916 | def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"), | |
5917 | GPR64, VectorIndexD>; | |
5918 | ||
5919 | def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"), | |
5920 | VectorIndexB>; | |
5921 | def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"), | |
5922 | VectorIndexH>; | |
5923 | def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"), | |
5924 | VectorIndexS>; | |
5925 | def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"), | |
5926 | VectorIndexD>; | |
5927 | } | |
5928 | ||
5929 | //---------------------------------------------------------------------------- | |
5930 | // AdvSIMD TBL/TBX | |
5931 | //---------------------------------------------------------------------------- | |
5932 | ||
5933 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
5934 | class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype, | |
5935 | RegisterOperand listtype, string asm, string kind> | |
5936 | : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm, | |
5937 | "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>, | |
5938 | Sched<[WriteV]> { | |
5939 | bits<5> Vd; | |
5940 | bits<5> Vn; | |
5941 | bits<5> Vm; | |
5942 | let Inst{31} = 0; | |
5943 | let Inst{30} = Q; | |
5944 | let Inst{29-21} = 0b001110000; | |
5945 | let Inst{20-16} = Vm; | |
5946 | let Inst{15} = 0; | |
5947 | let Inst{14-13} = len; | |
5948 | let Inst{12} = op; | |
5949 | let Inst{11-10} = 0b00; | |
5950 | let Inst{9-5} = Vn; | |
5951 | let Inst{4-0} = Vd; | |
5952 | } | |
5953 | ||
5954 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
5955 | class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype, | |
5956 | RegisterOperand listtype, string asm, string kind> | |
5957 | : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm, | |
5958 | "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>, | |
5959 | Sched<[WriteV]> { | |
5960 | bits<5> Vd; | |
5961 | bits<5> Vn; | |
5962 | bits<5> Vm; | |
5963 | let Inst{31} = 0; | |
5964 | let Inst{30} = Q; | |
5965 | let Inst{29-21} = 0b001110000; | |
5966 | let Inst{20-16} = Vm; | |
5967 | let Inst{15} = 0; | |
5968 | let Inst{14-13} = len; | |
5969 | let Inst{12} = op; | |
5970 | let Inst{11-10} = 0b00; | |
5971 | let Inst{9-5} = Vn; | |
5972 | let Inst{4-0} = Vd; | |
5973 | } | |
5974 | ||
5975 | class SIMDTableLookupAlias<string asm, Instruction inst, | |
5976 | RegisterOperand vectype, RegisterOperand listtype> | |
5977 | : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"), | |
5978 | (inst vectype:$dst, listtype:$lst, vectype:$index), 0>; | |
5979 | ||
5980 | multiclass SIMDTableLookup<bit op, string asm> { | |
5981 | def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b, | |
5982 | asm, ".8b">; | |
5983 | def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b, | |
5984 | asm, ".8b">; | |
5985 | def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b, | |
5986 | asm, ".8b">; | |
5987 | def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b, | |
5988 | asm, ".8b">; | |
5989 | def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b, | |
5990 | asm, ".16b">; | |
5991 | def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b, | |
5992 | asm, ".16b">; | |
5993 | def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b, | |
5994 | asm, ".16b">; | |
5995 | def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b, | |
5996 | asm, ".16b">; | |
5997 | ||
5998 | def : SIMDTableLookupAlias<asm # ".8b", | |
5999 | !cast<Instruction>(NAME#"v8i8One"), | |
6000 | V64, VecListOne128>; | |
6001 | def : SIMDTableLookupAlias<asm # ".8b", | |
6002 | !cast<Instruction>(NAME#"v8i8Two"), | |
6003 | V64, VecListTwo128>; | |
6004 | def : SIMDTableLookupAlias<asm # ".8b", | |
6005 | !cast<Instruction>(NAME#"v8i8Three"), | |
6006 | V64, VecListThree128>; | |
6007 | def : SIMDTableLookupAlias<asm # ".8b", | |
6008 | !cast<Instruction>(NAME#"v8i8Four"), | |
6009 | V64, VecListFour128>; | |
6010 | def : SIMDTableLookupAlias<asm # ".16b", | |
6011 | !cast<Instruction>(NAME#"v16i8One"), | |
6012 | V128, VecListOne128>; | |
6013 | def : SIMDTableLookupAlias<asm # ".16b", | |
6014 | !cast<Instruction>(NAME#"v16i8Two"), | |
6015 | V128, VecListTwo128>; | |
6016 | def : SIMDTableLookupAlias<asm # ".16b", | |
6017 | !cast<Instruction>(NAME#"v16i8Three"), | |
6018 | V128, VecListThree128>; | |
6019 | def : SIMDTableLookupAlias<asm # ".16b", | |
6020 | !cast<Instruction>(NAME#"v16i8Four"), | |
6021 | V128, VecListFour128>; | |
6022 | } | |
6023 | ||
6024 | multiclass SIMDTableLookupTied<bit op, string asm> { | |
6025 | def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b, | |
6026 | asm, ".8b">; | |
6027 | def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b, | |
6028 | asm, ".8b">; | |
6029 | def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b, | |
6030 | asm, ".8b">; | |
6031 | def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b, | |
6032 | asm, ".8b">; | |
6033 | def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b, | |
6034 | asm, ".16b">; | |
6035 | def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b, | |
6036 | asm, ".16b">; | |
6037 | def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b, | |
6038 | asm, ".16b">; | |
6039 | def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b, | |
6040 | asm, ".16b">; | |
6041 | ||
6042 | def : SIMDTableLookupAlias<asm # ".8b", | |
6043 | !cast<Instruction>(NAME#"v8i8One"), | |
6044 | V64, VecListOne128>; | |
6045 | def : SIMDTableLookupAlias<asm # ".8b", | |
6046 | !cast<Instruction>(NAME#"v8i8Two"), | |
6047 | V64, VecListTwo128>; | |
6048 | def : SIMDTableLookupAlias<asm # ".8b", | |
6049 | !cast<Instruction>(NAME#"v8i8Three"), | |
6050 | V64, VecListThree128>; | |
6051 | def : SIMDTableLookupAlias<asm # ".8b", | |
6052 | !cast<Instruction>(NAME#"v8i8Four"), | |
6053 | V64, VecListFour128>; | |
6054 | def : SIMDTableLookupAlias<asm # ".16b", | |
6055 | !cast<Instruction>(NAME#"v16i8One"), | |
6056 | V128, VecListOne128>; | |
6057 | def : SIMDTableLookupAlias<asm # ".16b", | |
6058 | !cast<Instruction>(NAME#"v16i8Two"), | |
6059 | V128, VecListTwo128>; | |
6060 | def : SIMDTableLookupAlias<asm # ".16b", | |
6061 | !cast<Instruction>(NAME#"v16i8Three"), | |
6062 | V128, VecListThree128>; | |
6063 | def : SIMDTableLookupAlias<asm # ".16b", | |
6064 | !cast<Instruction>(NAME#"v16i8Four"), | |
6065 | V128, VecListFour128>; | |
6066 | } | |
6067 | ||
6068 | ||
6069 | //---------------------------------------------------------------------------- | |
6070 | // AdvSIMD scalar CPY | |
6071 | //---------------------------------------------------------------------------- | |
6072 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
6073 | class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype, | |
6074 | string kind, Operand idxtype> | |
6075 | : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov", | |
6076 | "{\t$dst, $src" # kind # "$idx" # | |
6077 | "|\t$dst, $src$idx}", "", []>, | |
6078 | Sched<[WriteV]> { | |
6079 | bits<5> dst; | |
6080 | bits<5> src; | |
6081 | let Inst{31-21} = 0b01011110000; | |
6082 | let Inst{15-10} = 0b000001; | |
6083 | let Inst{9-5} = src; | |
6084 | let Inst{4-0} = dst; | |
6085 | } | |
6086 | ||
6087 | class SIMDScalarCPYAlias<string asm, string size, Instruction inst, | |
6088 | RegisterClass regtype, RegisterOperand vectype, Operand idxtype> | |
6089 | : InstAlias<asm # "{\t$dst, $src" # size # "$index" # | |
6090 | # "|\t$dst, $src$index}", | |
6091 | (inst regtype:$dst, vectype:$src, idxtype:$index), 0>; | |
6092 | ||
6093 | ||
6094 | multiclass SIMDScalarCPY<string asm> { | |
6095 | def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> { | |
6096 | bits<4> idx; | |
6097 | let Inst{20-17} = idx; | |
6098 | let Inst{16} = 1; | |
6099 | } | |
6100 | def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> { | |
6101 | bits<3> idx; | |
6102 | let Inst{20-18} = idx; | |
6103 | let Inst{17-16} = 0b10; | |
6104 | } | |
6105 | def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> { | |
6106 | bits<2> idx; | |
6107 | let Inst{20-19} = idx; | |
6108 | let Inst{18-16} = 0b100; | |
6109 | } | |
6110 | def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> { | |
6111 | bits<1> idx; | |
6112 | let Inst{20} = idx; | |
6113 | let Inst{19-16} = 0b1000; | |
6114 | } | |
6115 | ||
6116 | def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src), | |
6117 | VectorIndexD:$idx)))), | |
6118 | (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>; | |
6119 | ||
6120 | // 'DUP' mnemonic aliases. | |
6121 | def : SIMDScalarCPYAlias<"dup", ".b", | |
6122 | !cast<Instruction>(NAME#"i8"), | |
6123 | FPR8, V128, VectorIndexB>; | |
6124 | def : SIMDScalarCPYAlias<"dup", ".h", | |
6125 | !cast<Instruction>(NAME#"i16"), | |
6126 | FPR16, V128, VectorIndexH>; | |
6127 | def : SIMDScalarCPYAlias<"dup", ".s", | |
6128 | !cast<Instruction>(NAME#"i32"), | |
6129 | FPR32, V128, VectorIndexS>; | |
6130 | def : SIMDScalarCPYAlias<"dup", ".d", | |
6131 | !cast<Instruction>(NAME#"i64"), | |
6132 | FPR64, V128, VectorIndexD>; | |
6133 | } | |
6134 | ||
6135 | //---------------------------------------------------------------------------- | |
6136 | // AdvSIMD modified immediate instructions | |
6137 | //---------------------------------------------------------------------------- | |
6138 | ||
6139 | class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops, | |
6140 | string asm, string op_string, | |
6141 | string cstr, list<dag> pattern> | |
6142 | : I<oops, iops, asm, op_string, cstr, pattern>, | |
6143 | Sched<[WriteV]> { | |
6144 | bits<5> Rd; | |
6145 | bits<8> imm8; | |
6146 | let Inst{31} = 0; | |
6147 | let Inst{30} = Q; | |
6148 | let Inst{29} = op; | |
6149 | let Inst{28-19} = 0b0111100000; | |
6150 | let Inst{18-16} = imm8{7-5}; | |
6151 | let Inst{11-10} = 0b01; | |
6152 | let Inst{9-5} = imm8{4-0}; | |
6153 | let Inst{4-0} = Rd; | |
6154 | } | |
6155 | ||
6156 | class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype, | |
6157 | Operand immtype, dag opt_shift_iop, | |
6158 | string opt_shift, string asm, string kind, | |
6159 | list<dag> pattern> | |
6160 | : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd), | |
6161 | !con((ins immtype:$imm8), opt_shift_iop), asm, | |
6162 | "{\t$Rd" # kind # ", $imm8" # opt_shift # | |
6163 | "|" # kind # "\t$Rd, $imm8" # opt_shift # "}", | |
6164 | "", pattern> { | |
6165 | let DecoderMethod = "DecodeModImmInstruction"; | |
6166 | } | |
6167 | ||
6168 | class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype, | |
6169 | Operand immtype, dag opt_shift_iop, | |
6170 | string opt_shift, string asm, string kind, | |
6171 | list<dag> pattern> | |
6172 | : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst), | |
6173 | !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop), | |
6174 | asm, "{\t$Rd" # kind # ", $imm8" # opt_shift # | |
6175 | "|" # kind # "\t$Rd, $imm8" # opt_shift # "}", | |
6176 | "$Rd = $dst", pattern> { | |
6177 | let DecoderMethod = "DecodeModImmTiedInstruction"; | |
6178 | } | |
6179 | ||
6180 | class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12, | |
6181 | RegisterOperand vectype, string asm, | |
6182 | string kind, list<dag> pattern> | |
6183 | : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255, | |
6184 | (ins logical_vec_shift:$shift), | |
6185 | "$shift", asm, kind, pattern> { | |
6186 | bits<2> shift; | |
6187 | let Inst{15} = b15_b12{1}; | |
6188 | let Inst{14-13} = shift; | |
6189 | let Inst{12} = b15_b12{0}; | |
6190 | } | |
6191 | ||
6192 | class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12, | |
6193 | RegisterOperand vectype, string asm, | |
6194 | string kind, list<dag> pattern> | |
6195 | : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255, | |
6196 | (ins logical_vec_shift:$shift), | |
6197 | "$shift", asm, kind, pattern> { | |
6198 | bits<2> shift; | |
6199 | let Inst{15} = b15_b12{1}; | |
6200 | let Inst{14-13} = shift; | |
6201 | let Inst{12} = b15_b12{0}; | |
6202 | } | |
6203 | ||
6204 | ||
6205 | class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12, | |
6206 | RegisterOperand vectype, string asm, | |
6207 | string kind, list<dag> pattern> | |
6208 | : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255, | |
6209 | (ins logical_vec_hw_shift:$shift), | |
6210 | "$shift", asm, kind, pattern> { | |
6211 | bits<2> shift; | |
6212 | let Inst{15} = b15_b12{1}; | |
6213 | let Inst{14} = 0; | |
6214 | let Inst{13} = shift{0}; | |
6215 | let Inst{12} = b15_b12{0}; | |
6216 | } | |
6217 | ||
6218 | class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12, | |
6219 | RegisterOperand vectype, string asm, | |
6220 | string kind, list<dag> pattern> | |
6221 | : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255, | |
6222 | (ins logical_vec_hw_shift:$shift), | |
6223 | "$shift", asm, kind, pattern> { | |
6224 | bits<2> shift; | |
6225 | let Inst{15} = b15_b12{1}; | |
6226 | let Inst{14} = 0; | |
6227 | let Inst{13} = shift{0}; | |
6228 | let Inst{12} = b15_b12{0}; | |
6229 | } | |
6230 | ||
6231 | multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode, | |
6232 | string asm> { | |
6233 | def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64, | |
6234 | asm, ".4h", []>; | |
6235 | def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128, | |
6236 | asm, ".8h", []>; | |
6237 | ||
6238 | def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64, | |
6239 | asm, ".2s", []>; | |
6240 | def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128, | |
6241 | asm, ".4s", []>; | |
6242 | } | |
6243 | ||
6244 | multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode, | |
6245 | bits<2> w_cmode, string asm, | |
6246 | SDNode OpNode> { | |
6247 | def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64, | |
6248 | asm, ".4h", | |
6249 | [(set (v4i16 V64:$dst), (OpNode V64:$Rd, | |
6250 | imm0_255:$imm8, | |
6251 | (i32 imm:$shift)))]>; | |
6252 | def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128, | |
6253 | asm, ".8h", | |
6254 | [(set (v8i16 V128:$dst), (OpNode V128:$Rd, | |
6255 | imm0_255:$imm8, | |
6256 | (i32 imm:$shift)))]>; | |
6257 | ||
6258 | def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64, | |
6259 | asm, ".2s", | |
6260 | [(set (v2i32 V64:$dst), (OpNode V64:$Rd, | |
6261 | imm0_255:$imm8, | |
6262 | (i32 imm:$shift)))]>; | |
6263 | def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128, | |
6264 | asm, ".4s", | |
6265 | [(set (v4i32 V128:$dst), (OpNode V128:$Rd, | |
6266 | imm0_255:$imm8, | |
6267 | (i32 imm:$shift)))]>; | |
6268 | } | |
6269 | ||
6270 | class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode, | |
6271 | RegisterOperand vectype, string asm, | |
6272 | string kind, list<dag> pattern> | |
6273 | : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255, | |
6274 | (ins move_vec_shift:$shift), | |
6275 | "$shift", asm, kind, pattern> { | |
6276 | bits<1> shift; | |
6277 | let Inst{15-13} = cmode{3-1}; | |
6278 | let Inst{12} = shift; | |
6279 | } | |
6280 | ||
6281 | class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode, | |
6282 | RegisterOperand vectype, | |
6283 | Operand imm_type, string asm, | |
6284 | string kind, list<dag> pattern> | |
6285 | : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "", | |
6286 | asm, kind, pattern> { | |
6287 | let Inst{15-12} = cmode; | |
6288 | } | |
6289 | ||
6290 | class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm, | |
6291 | list<dag> pattern> | |
6292 | : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm, | |
6293 | "\t$Rd, $imm8", "", pattern> { | |
6294 | let Inst{15-12} = cmode; | |
6295 | let DecoderMethod = "DecodeModImmInstruction"; | |
6296 | } | |
6297 | ||
6298 | //---------------------------------------------------------------------------- | |
6299 | // AdvSIMD indexed element | |
6300 | //---------------------------------------------------------------------------- | |
6301 | ||
6302 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
6303 | class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc, | |
6304 | RegisterOperand dst_reg, RegisterOperand lhs_reg, | |
6305 | RegisterOperand rhs_reg, Operand vec_idx, string asm, | |
6306 | string apple_kind, string dst_kind, string lhs_kind, | |
6307 | string rhs_kind, list<dag> pattern> | |
6308 | : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), | |
6309 | asm, | |
6310 | "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" # | |
6311 | "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>, | |
6312 | Sched<[WriteV]> { | |
6313 | bits<5> Rd; | |
6314 | bits<5> Rn; | |
6315 | bits<5> Rm; | |
6316 | ||
6317 | let Inst{31} = 0; | |
6318 | let Inst{30} = Q; | |
6319 | let Inst{29} = U; | |
6320 | let Inst{28} = Scalar; | |
6321 | let Inst{27-24} = 0b1111; | |
6322 | let Inst{23-22} = size; | |
6323 | // Bit 21 must be set by the derived class. | |
6324 | let Inst{20-16} = Rm; | |
6325 | let Inst{15-12} = opc; | |
6326 | // Bit 11 must be set by the derived class. | |
6327 | let Inst{10} = 0; | |
6328 | let Inst{9-5} = Rn; | |
6329 | let Inst{4-0} = Rd; | |
6330 | } | |
6331 | ||
6332 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
6333 | class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc, | |
6334 | RegisterOperand dst_reg, RegisterOperand lhs_reg, | |
6335 | RegisterOperand rhs_reg, Operand vec_idx, string asm, | |
6336 | string apple_kind, string dst_kind, string lhs_kind, | |
6337 | string rhs_kind, list<dag> pattern> | |
6338 | : I<(outs dst_reg:$dst), | |
6339 | (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm, | |
6340 | "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" # | |
6341 | "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>, | |
6342 | Sched<[WriteV]> { | |
6343 | bits<5> Rd; | |
6344 | bits<5> Rn; | |
6345 | bits<5> Rm; | |
6346 | ||
6347 | let Inst{31} = 0; | |
6348 | let Inst{30} = Q; | |
6349 | let Inst{29} = U; | |
6350 | let Inst{28} = Scalar; | |
6351 | let Inst{27-24} = 0b1111; | |
6352 | let Inst{23-22} = size; | |
6353 | // Bit 21 must be set by the derived class. | |
6354 | let Inst{20-16} = Rm; | |
6355 | let Inst{15-12} = opc; | |
6356 | // Bit 11 must be set by the derived class. | |
6357 | let Inst{10} = 0; | |
6358 | let Inst{9-5} = Rn; | |
6359 | let Inst{4-0} = Rd; | |
6360 | } | |
6361 | ||
6362 | multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm, | |
6363 | SDPatternOperator OpNode> { | |
6364 | def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc, | |
6365 | V64, V64, | |
6366 | V128, VectorIndexS, | |
6367 | asm, ".2s", ".2s", ".2s", ".s", | |
6368 | [(set (v2f32 V64:$Rd), | |
6369 | (OpNode (v2f32 V64:$Rn), | |
6370 | (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6371 | bits<2> idx; | |
6372 | let Inst{11} = idx{1}; | |
6373 | let Inst{21} = idx{0}; | |
6374 | } | |
6375 | ||
6376 | def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc, | |
6377 | V128, V128, | |
6378 | V128, VectorIndexS, | |
6379 | asm, ".4s", ".4s", ".4s", ".s", | |
6380 | [(set (v4f32 V128:$Rd), | |
6381 | (OpNode (v4f32 V128:$Rn), | |
6382 | (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6383 | bits<2> idx; | |
6384 | let Inst{11} = idx{1}; | |
6385 | let Inst{21} = idx{0}; | |
6386 | } | |
6387 | ||
6388 | def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc, | |
6389 | V128, V128, | |
6390 | V128, VectorIndexD, | |
6391 | asm, ".2d", ".2d", ".2d", ".d", | |
6392 | [(set (v2f64 V128:$Rd), | |
6393 | (OpNode (v2f64 V128:$Rn), | |
6394 | (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> { | |
6395 | bits<1> idx; | |
6396 | let Inst{11} = idx{0}; | |
6397 | let Inst{21} = 0; | |
6398 | } | |
6399 | ||
6400 | def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc, | |
6401 | FPR32Op, FPR32Op, V128, VectorIndexS, | |
6402 | asm, ".s", "", "", ".s", | |
6403 | [(set (f32 FPR32Op:$Rd), | |
6404 | (OpNode (f32 FPR32Op:$Rn), | |
6405 | (f32 (vector_extract (v4f32 V128:$Rm), | |
6406 | VectorIndexS:$idx))))]> { | |
6407 | bits<2> idx; | |
6408 | let Inst{11} = idx{1}; | |
6409 | let Inst{21} = idx{0}; | |
6410 | } | |
6411 | ||
6412 | def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc, | |
6413 | FPR64Op, FPR64Op, V128, VectorIndexD, | |
6414 | asm, ".d", "", "", ".d", | |
6415 | [(set (f64 FPR64Op:$Rd), | |
6416 | (OpNode (f64 FPR64Op:$Rn), | |
6417 | (f64 (vector_extract (v2f64 V128:$Rm), | |
6418 | VectorIndexD:$idx))))]> { | |
6419 | bits<1> idx; | |
6420 | let Inst{11} = idx{0}; | |
6421 | let Inst{21} = 0; | |
6422 | } | |
6423 | } | |
6424 | ||
6425 | multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> { | |
6426 | // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar. | |
6427 | def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), | |
6428 | (AArch64duplane32 (v4f32 V128:$Rm), | |
6429 | VectorIndexS:$idx))), | |
6430 | (!cast<Instruction>(INST # v2i32_indexed) | |
6431 | V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>; | |
6432 | def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), | |
6433 | (AArch64dup (f32 FPR32Op:$Rm)))), | |
6434 | (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn, | |
6435 | (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>; | |
6436 | ||
6437 | ||
6438 | // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar. | |
6439 | def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), | |
6440 | (AArch64duplane32 (v4f32 V128:$Rm), | |
6441 | VectorIndexS:$idx))), | |
6442 | (!cast<Instruction>(INST # "v4i32_indexed") | |
6443 | V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>; | |
6444 | def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), | |
6445 | (AArch64dup (f32 FPR32Op:$Rm)))), | |
6446 | (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn, | |
6447 | (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>; | |
6448 | ||
6449 | // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar. | |
6450 | def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), | |
6451 | (AArch64duplane64 (v2f64 V128:$Rm), | |
6452 | VectorIndexD:$idx))), | |
6453 | (!cast<Instruction>(INST # "v2i64_indexed") | |
6454 | V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>; | |
6455 | def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), | |
6456 | (AArch64dup (f64 FPR64Op:$Rm)))), | |
6457 | (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn, | |
6458 | (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>; | |
6459 | ||
6460 | // 2 variants for 32-bit scalar version: extract from .2s or from .4s | |
6461 | def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn), | |
6462 | (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))), | |
6463 | (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn, | |
6464 | V128:$Rm, VectorIndexS:$idx)>; | |
6465 | def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn), | |
6466 | (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))), | |
6467 | (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn, | |
6468 | (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>; | |
6469 | ||
6470 | // 1 variant for 64-bit scalar version: extract from .1d or from .2d | |
6471 | def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn), | |
6472 | (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))), | |
6473 | (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn, | |
6474 | V128:$Rm, VectorIndexD:$idx)>; | |
6475 | } | |
6476 | ||
6477 | multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> { | |
6478 | def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64, | |
6479 | V128, VectorIndexS, | |
6480 | asm, ".2s", ".2s", ".2s", ".s", []> { | |
6481 | bits<2> idx; | |
6482 | let Inst{11} = idx{1}; | |
6483 | let Inst{21} = idx{0}; | |
6484 | } | |
6485 | ||
6486 | def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc, | |
6487 | V128, V128, | |
6488 | V128, VectorIndexS, | |
6489 | asm, ".4s", ".4s", ".4s", ".s", []> { | |
6490 | bits<2> idx; | |
6491 | let Inst{11} = idx{1}; | |
6492 | let Inst{21} = idx{0}; | |
6493 | } | |
6494 | ||
6495 | def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc, | |
6496 | V128, V128, | |
6497 | V128, VectorIndexD, | |
6498 | asm, ".2d", ".2d", ".2d", ".d", []> { | |
6499 | bits<1> idx; | |
6500 | let Inst{11} = idx{0}; | |
6501 | let Inst{21} = 0; | |
6502 | } | |
6503 | ||
6504 | ||
6505 | def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc, | |
6506 | FPR32Op, FPR32Op, V128, VectorIndexS, | |
6507 | asm, ".s", "", "", ".s", []> { | |
6508 | bits<2> idx; | |
6509 | let Inst{11} = idx{1}; | |
6510 | let Inst{21} = idx{0}; | |
6511 | } | |
6512 | ||
6513 | def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc, | |
6514 | FPR64Op, FPR64Op, V128, VectorIndexD, | |
6515 | asm, ".d", "", "", ".d", []> { | |
6516 | bits<1> idx; | |
6517 | let Inst{11} = idx{0}; | |
6518 | let Inst{21} = 0; | |
6519 | } | |
6520 | } | |
6521 | ||
6522 | multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm, | |
6523 | SDPatternOperator OpNode> { | |
6524 | def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64, | |
6525 | V128_lo, VectorIndexH, | |
6526 | asm, ".4h", ".4h", ".4h", ".h", | |
6527 | [(set (v4i16 V64:$Rd), | |
6528 | (OpNode (v4i16 V64:$Rn), | |
6529 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6530 | bits<3> idx; | |
6531 | let Inst{11} = idx{2}; | |
6532 | let Inst{21} = idx{1}; | |
6533 | let Inst{20} = idx{0}; | |
6534 | } | |
6535 | ||
6536 | def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc, | |
6537 | V128, V128, | |
6538 | V128_lo, VectorIndexH, | |
6539 | asm, ".8h", ".8h", ".8h", ".h", | |
6540 | [(set (v8i16 V128:$Rd), | |
6541 | (OpNode (v8i16 V128:$Rn), | |
6542 | (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6543 | bits<3> idx; | |
6544 | let Inst{11} = idx{2}; | |
6545 | let Inst{21} = idx{1}; | |
6546 | let Inst{20} = idx{0}; | |
6547 | } | |
6548 | ||
6549 | def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc, | |
6550 | V64, V64, | |
6551 | V128, VectorIndexS, | |
6552 | asm, ".2s", ".2s", ".2s", ".s", | |
6553 | [(set (v2i32 V64:$Rd), | |
6554 | (OpNode (v2i32 V64:$Rn), | |
6555 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6556 | bits<2> idx; | |
6557 | let Inst{11} = idx{1}; | |
6558 | let Inst{21} = idx{0}; | |
6559 | } | |
6560 | ||
6561 | def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc, | |
6562 | V128, V128, | |
6563 | V128, VectorIndexS, | |
6564 | asm, ".4s", ".4s", ".4s", ".s", | |
6565 | [(set (v4i32 V128:$Rd), | |
6566 | (OpNode (v4i32 V128:$Rn), | |
6567 | (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6568 | bits<2> idx; | |
6569 | let Inst{11} = idx{1}; | |
6570 | let Inst{21} = idx{0}; | |
6571 | } | |
6572 | ||
6573 | def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc, | |
6574 | FPR16Op, FPR16Op, V128_lo, VectorIndexH, | |
6575 | asm, ".h", "", "", ".h", []> { | |
6576 | bits<3> idx; | |
6577 | let Inst{11} = idx{2}; | |
6578 | let Inst{21} = idx{1}; | |
6579 | let Inst{20} = idx{0}; | |
6580 | } | |
6581 | ||
6582 | def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc, | |
6583 | FPR32Op, FPR32Op, V128, VectorIndexS, | |
6584 | asm, ".s", "", "", ".s", | |
6585 | [(set (i32 FPR32Op:$Rd), | |
6586 | (OpNode FPR32Op:$Rn, | |
6587 | (i32 (vector_extract (v4i32 V128:$Rm), | |
6588 | VectorIndexS:$idx))))]> { | |
6589 | bits<2> idx; | |
6590 | let Inst{11} = idx{1}; | |
6591 | let Inst{21} = idx{0}; | |
6592 | } | |
6593 | } | |
6594 | ||
6595 | multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm, | |
6596 | SDPatternOperator OpNode> { | |
6597 | def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, | |
6598 | V64, V64, | |
6599 | V128_lo, VectorIndexH, | |
6600 | asm, ".4h", ".4h", ".4h", ".h", | |
6601 | [(set (v4i16 V64:$Rd), | |
6602 | (OpNode (v4i16 V64:$Rn), | |
6603 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6604 | bits<3> idx; | |
6605 | let Inst{11} = idx{2}; | |
6606 | let Inst{21} = idx{1}; | |
6607 | let Inst{20} = idx{0}; | |
6608 | } | |
6609 | ||
6610 | def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc, | |
6611 | V128, V128, | |
6612 | V128_lo, VectorIndexH, | |
6613 | asm, ".8h", ".8h", ".8h", ".h", | |
6614 | [(set (v8i16 V128:$Rd), | |
6615 | (OpNode (v8i16 V128:$Rn), | |
6616 | (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6617 | bits<3> idx; | |
6618 | let Inst{11} = idx{2}; | |
6619 | let Inst{21} = idx{1}; | |
6620 | let Inst{20} = idx{0}; | |
6621 | } | |
6622 | ||
6623 | def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc, | |
6624 | V64, V64, | |
6625 | V128, VectorIndexS, | |
6626 | asm, ".2s", ".2s", ".2s", ".s", | |
6627 | [(set (v2i32 V64:$Rd), | |
6628 | (OpNode (v2i32 V64:$Rn), | |
6629 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6630 | bits<2> idx; | |
6631 | let Inst{11} = idx{1}; | |
6632 | let Inst{21} = idx{0}; | |
6633 | } | |
6634 | ||
6635 | def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc, | |
6636 | V128, V128, | |
6637 | V128, VectorIndexS, | |
6638 | asm, ".4s", ".4s", ".4s", ".s", | |
6639 | [(set (v4i32 V128:$Rd), | |
6640 | (OpNode (v4i32 V128:$Rn), | |
6641 | (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6642 | bits<2> idx; | |
6643 | let Inst{11} = idx{1}; | |
6644 | let Inst{21} = idx{0}; | |
6645 | } | |
6646 | } | |
6647 | ||
6648 | multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm, | |
6649 | SDPatternOperator OpNode> { | |
6650 | def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64, | |
6651 | V128_lo, VectorIndexH, | |
6652 | asm, ".4h", ".4h", ".4h", ".h", | |
6653 | [(set (v4i16 V64:$dst), | |
6654 | (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn), | |
6655 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6656 | bits<3> idx; | |
6657 | let Inst{11} = idx{2}; | |
6658 | let Inst{21} = idx{1}; | |
6659 | let Inst{20} = idx{0}; | |
6660 | } | |
6661 | ||
6662 | def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc, | |
6663 | V128, V128, | |
6664 | V128_lo, VectorIndexH, | |
6665 | asm, ".8h", ".8h", ".8h", ".h", | |
6666 | [(set (v8i16 V128:$dst), | |
6667 | (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), | |
6668 | (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6669 | bits<3> idx; | |
6670 | let Inst{11} = idx{2}; | |
6671 | let Inst{21} = idx{1}; | |
6672 | let Inst{20} = idx{0}; | |
6673 | } | |
6674 | ||
6675 | def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, | |
6676 | V64, V64, | |
6677 | V128, VectorIndexS, | |
6678 | asm, ".2s", ".2s", ".2s", ".s", | |
6679 | [(set (v2i32 V64:$dst), | |
6680 | (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), | |
6681 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6682 | bits<2> idx; | |
6683 | let Inst{11} = idx{1}; | |
6684 | let Inst{21} = idx{0}; | |
6685 | } | |
6686 | ||
6687 | def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc, | |
6688 | V128, V128, | |
6689 | V128, VectorIndexS, | |
6690 | asm, ".4s", ".4s", ".4s", ".s", | |
6691 | [(set (v4i32 V128:$dst), | |
6692 | (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), | |
6693 | (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6694 | bits<2> idx; | |
6695 | let Inst{11} = idx{1}; | |
6696 | let Inst{21} = idx{0}; | |
6697 | } | |
6698 | } | |
6699 | ||
6700 | multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm, | |
6701 | SDPatternOperator OpNode> { | |
6702 | def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, | |
6703 | V128, V64, | |
6704 | V128_lo, VectorIndexH, | |
6705 | asm, ".4s", ".4s", ".4h", ".h", | |
6706 | [(set (v4i32 V128:$Rd), | |
6707 | (OpNode (v4i16 V64:$Rn), | |
6708 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6709 | bits<3> idx; | |
6710 | let Inst{11} = idx{2}; | |
6711 | let Inst{21} = idx{1}; | |
6712 | let Inst{20} = idx{0}; | |
6713 | } | |
6714 | ||
6715 | def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc, | |
6716 | V128, V128, | |
6717 | V128_lo, VectorIndexH, | |
6718 | asm#"2", ".4s", ".4s", ".8h", ".h", | |
6719 | [(set (v4i32 V128:$Rd), | |
6720 | (OpNode (extract_high_v8i16 V128:$Rn), | |
6721 | (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), | |
6722 | VectorIndexH:$idx))))]> { | |
6723 | ||
6724 | bits<3> idx; | |
6725 | let Inst{11} = idx{2}; | |
6726 | let Inst{21} = idx{1}; | |
6727 | let Inst{20} = idx{0}; | |
6728 | } | |
6729 | ||
6730 | def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc, | |
6731 | V128, V64, | |
6732 | V128, VectorIndexS, | |
6733 | asm, ".2d", ".2d", ".2s", ".s", | |
6734 | [(set (v2i64 V128:$Rd), | |
6735 | (OpNode (v2i32 V64:$Rn), | |
6736 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6737 | bits<2> idx; | |
6738 | let Inst{11} = idx{1}; | |
6739 | let Inst{21} = idx{0}; | |
6740 | } | |
6741 | ||
6742 | def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc, | |
6743 | V128, V128, | |
6744 | V128, VectorIndexS, | |
6745 | asm#"2", ".2d", ".2d", ".4s", ".s", | |
6746 | [(set (v2i64 V128:$Rd), | |
6747 | (OpNode (extract_high_v4i32 V128:$Rn), | |
6748 | (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm), | |
6749 | VectorIndexS:$idx))))]> { | |
6750 | bits<2> idx; | |
6751 | let Inst{11} = idx{1}; | |
6752 | let Inst{21} = idx{0}; | |
6753 | } | |
6754 | ||
6755 | def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc, | |
6756 | FPR32Op, FPR16Op, V128_lo, VectorIndexH, | |
6757 | asm, ".h", "", "", ".h", []> { | |
6758 | bits<3> idx; | |
6759 | let Inst{11} = idx{2}; | |
6760 | let Inst{21} = idx{1}; | |
6761 | let Inst{20} = idx{0}; | |
6762 | } | |
6763 | ||
6764 | def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc, | |
6765 | FPR64Op, FPR32Op, V128, VectorIndexS, | |
6766 | asm, ".s", "", "", ".s", []> { | |
6767 | bits<2> idx; | |
6768 | let Inst{11} = idx{1}; | |
6769 | let Inst{21} = idx{0}; | |
6770 | } | |
6771 | } | |
6772 | ||
6773 | multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm, | |
6774 | SDPatternOperator Accum> { | |
6775 | def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, | |
6776 | V128, V64, | |
6777 | V128_lo, VectorIndexH, | |
6778 | asm, ".4s", ".4s", ".4h", ".h", | |
6779 | [(set (v4i32 V128:$dst), | |
6780 | (Accum (v4i32 V128:$Rd), | |
6781 | (v4i32 (int_aarch64_neon_sqdmull | |
6782 | (v4i16 V64:$Rn), | |
6783 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), | |
6784 | VectorIndexH:$idx))))))]> { | |
6785 | bits<3> idx; | |
6786 | let Inst{11} = idx{2}; | |
6787 | let Inst{21} = idx{1}; | |
6788 | let Inst{20} = idx{0}; | |
6789 | } | |
6790 | ||
6791 | // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an | |
6792 | // intermediate EXTRACT_SUBREG would be untyped. | |
6793 | def : Pat<(i32 (Accum (i32 FPR32Op:$Rd), | |
6794 | (i32 (vector_extract (v4i32 | |
6795 | (int_aarch64_neon_sqdmull (v4i16 V64:$Rn), | |
6796 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), | |
6797 | VectorIndexH:$idx)))), | |
6798 | (i64 0))))), | |
6799 | (EXTRACT_SUBREG | |
6800 | (!cast<Instruction>(NAME # v4i16_indexed) | |
6801 | (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn, | |
6802 | V128_lo:$Rm, VectorIndexH:$idx), | |
6803 | ssub)>; | |
6804 | ||
6805 | def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc, | |
6806 | V128, V128, | |
6807 | V128_lo, VectorIndexH, | |
6808 | asm#"2", ".4s", ".4s", ".8h", ".h", | |
6809 | [(set (v4i32 V128:$dst), | |
6810 | (Accum (v4i32 V128:$Rd), | |
6811 | (v4i32 (int_aarch64_neon_sqdmull | |
6812 | (extract_high_v8i16 V128:$Rn), | |
6813 | (extract_high_v8i16 | |
6814 | (AArch64duplane16 (v8i16 V128_lo:$Rm), | |
6815 | VectorIndexH:$idx))))))]> { | |
6816 | bits<3> idx; | |
6817 | let Inst{11} = idx{2}; | |
6818 | let Inst{21} = idx{1}; | |
6819 | let Inst{20} = idx{0}; | |
6820 | } | |
6821 | ||
6822 | def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, | |
6823 | V128, V64, | |
6824 | V128, VectorIndexS, | |
6825 | asm, ".2d", ".2d", ".2s", ".s", | |
6826 | [(set (v2i64 V128:$dst), | |
6827 | (Accum (v2i64 V128:$Rd), | |
6828 | (v2i64 (int_aarch64_neon_sqdmull | |
6829 | (v2i32 V64:$Rn), | |
6830 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), | |
6831 | VectorIndexS:$idx))))))]> { | |
6832 | bits<2> idx; | |
6833 | let Inst{11} = idx{1}; | |
6834 | let Inst{21} = idx{0}; | |
6835 | } | |
6836 | ||
6837 | def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc, | |
6838 | V128, V128, | |
6839 | V128, VectorIndexS, | |
6840 | asm#"2", ".2d", ".2d", ".4s", ".s", | |
6841 | [(set (v2i64 V128:$dst), | |
6842 | (Accum (v2i64 V128:$Rd), | |
6843 | (v2i64 (int_aarch64_neon_sqdmull | |
6844 | (extract_high_v4i32 V128:$Rn), | |
6845 | (extract_high_v4i32 | |
6846 | (AArch64duplane32 (v4i32 V128:$Rm), | |
6847 | VectorIndexS:$idx))))))]> { | |
6848 | bits<2> idx; | |
6849 | let Inst{11} = idx{1}; | |
6850 | let Inst{21} = idx{0}; | |
6851 | } | |
6852 | ||
6853 | def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc, | |
6854 | FPR32Op, FPR16Op, V128_lo, VectorIndexH, | |
6855 | asm, ".h", "", "", ".h", []> { | |
6856 | bits<3> idx; | |
6857 | let Inst{11} = idx{2}; | |
6858 | let Inst{21} = idx{1}; | |
6859 | let Inst{20} = idx{0}; | |
6860 | } | |
6861 | ||
6862 | ||
6863 | def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc, | |
6864 | FPR64Op, FPR32Op, V128, VectorIndexS, | |
6865 | asm, ".s", "", "", ".s", | |
6866 | [(set (i64 FPR64Op:$dst), | |
6867 | (Accum (i64 FPR64Op:$Rd), | |
6868 | (i64 (int_aarch64_neon_sqdmulls_scalar | |
6869 | (i32 FPR32Op:$Rn), | |
6870 | (i32 (vector_extract (v4i32 V128:$Rm), | |
6871 | VectorIndexS:$idx))))))]> { | |
6872 | ||
6873 | bits<2> idx; | |
6874 | let Inst{11} = idx{1}; | |
6875 | let Inst{21} = idx{0}; | |
6876 | } | |
6877 | } | |
6878 | ||
6879 | multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm, | |
6880 | SDPatternOperator OpNode> { | |
6881 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
6882 | def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, | |
6883 | V128, V64, | |
6884 | V128_lo, VectorIndexH, | |
6885 | asm, ".4s", ".4s", ".4h", ".h", | |
6886 | [(set (v4i32 V128:$Rd), | |
6887 | (OpNode (v4i16 V64:$Rn), | |
6888 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6889 | bits<3> idx; | |
6890 | let Inst{11} = idx{2}; | |
6891 | let Inst{21} = idx{1}; | |
6892 | let Inst{20} = idx{0}; | |
6893 | } | |
6894 | ||
6895 | def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc, | |
6896 | V128, V128, | |
6897 | V128_lo, VectorIndexH, | |
6898 | asm#"2", ".4s", ".4s", ".8h", ".h", | |
6899 | [(set (v4i32 V128:$Rd), | |
6900 | (OpNode (extract_high_v8i16 V128:$Rn), | |
6901 | (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), | |
6902 | VectorIndexH:$idx))))]> { | |
6903 | ||
6904 | bits<3> idx; | |
6905 | let Inst{11} = idx{2}; | |
6906 | let Inst{21} = idx{1}; | |
6907 | let Inst{20} = idx{0}; | |
6908 | } | |
6909 | ||
6910 | def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc, | |
6911 | V128, V64, | |
6912 | V128, VectorIndexS, | |
6913 | asm, ".2d", ".2d", ".2s", ".s", | |
6914 | [(set (v2i64 V128:$Rd), | |
6915 | (OpNode (v2i32 V64:$Rn), | |
6916 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6917 | bits<2> idx; | |
6918 | let Inst{11} = idx{1}; | |
6919 | let Inst{21} = idx{0}; | |
6920 | } | |
6921 | ||
6922 | def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc, | |
6923 | V128, V128, | |
6924 | V128, VectorIndexS, | |
6925 | asm#"2", ".2d", ".2d", ".4s", ".s", | |
6926 | [(set (v2i64 V128:$Rd), | |
6927 | (OpNode (extract_high_v4i32 V128:$Rn), | |
6928 | (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm), | |
6929 | VectorIndexS:$idx))))]> { | |
6930 | bits<2> idx; | |
6931 | let Inst{11} = idx{1}; | |
6932 | let Inst{21} = idx{0}; | |
6933 | } | |
6934 | } | |
6935 | } | |
6936 | ||
6937 | multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm, | |
6938 | SDPatternOperator OpNode> { | |
6939 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { | |
6940 | def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, | |
6941 | V128, V64, | |
6942 | V128_lo, VectorIndexH, | |
6943 | asm, ".4s", ".4s", ".4h", ".h", | |
6944 | [(set (v4i32 V128:$dst), | |
6945 | (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), | |
6946 | (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> { | |
6947 | bits<3> idx; | |
6948 | let Inst{11} = idx{2}; | |
6949 | let Inst{21} = idx{1}; | |
6950 | let Inst{20} = idx{0}; | |
6951 | } | |
6952 | ||
6953 | def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc, | |
6954 | V128, V128, | |
6955 | V128_lo, VectorIndexH, | |
6956 | asm#"2", ".4s", ".4s", ".8h", ".h", | |
6957 | [(set (v4i32 V128:$dst), | |
6958 | (OpNode (v4i32 V128:$Rd), | |
6959 | (extract_high_v8i16 V128:$Rn), | |
6960 | (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), | |
6961 | VectorIndexH:$idx))))]> { | |
6962 | bits<3> idx; | |
6963 | let Inst{11} = idx{2}; | |
6964 | let Inst{21} = idx{1}; | |
6965 | let Inst{20} = idx{0}; | |
6966 | } | |
6967 | ||
6968 | def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, | |
6969 | V128, V64, | |
6970 | V128, VectorIndexS, | |
6971 | asm, ".2d", ".2d", ".2s", ".s", | |
6972 | [(set (v2i64 V128:$dst), | |
6973 | (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), | |
6974 | (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> { | |
6975 | bits<2> idx; | |
6976 | let Inst{11} = idx{1}; | |
6977 | let Inst{21} = idx{0}; | |
6978 | } | |
6979 | ||
6980 | def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc, | |
6981 | V128, V128, | |
6982 | V128, VectorIndexS, | |
6983 | asm#"2", ".2d", ".2d", ".4s", ".s", | |
6984 | [(set (v2i64 V128:$dst), | |
6985 | (OpNode (v2i64 V128:$Rd), | |
6986 | (extract_high_v4i32 V128:$Rn), | |
6987 | (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm), | |
6988 | VectorIndexS:$idx))))]> { | |
6989 | bits<2> idx; | |
6990 | let Inst{11} = idx{1}; | |
6991 | let Inst{21} = idx{0}; | |
6992 | } | |
6993 | } | |
6994 | } | |
6995 | ||
6996 | //---------------------------------------------------------------------------- | |
6997 | // AdvSIMD scalar shift by immediate | |
6998 | //---------------------------------------------------------------------------- | |
6999 | ||
7000 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
7001 | class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm, | |
7002 | RegisterClass regtype1, RegisterClass regtype2, | |
7003 | Operand immtype, string asm, list<dag> pattern> | |
7004 | : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm), | |
7005 | asm, "\t$Rd, $Rn, $imm", "", pattern>, | |
7006 | Sched<[WriteV]> { | |
7007 | bits<5> Rd; | |
7008 | bits<5> Rn; | |
7009 | bits<7> imm; | |
7010 | let Inst{31-30} = 0b01; | |
7011 | let Inst{29} = U; | |
7012 | let Inst{28-23} = 0b111110; | |
7013 | let Inst{22-16} = fixed_imm; | |
7014 | let Inst{15-11} = opc; | |
7015 | let Inst{10} = 1; | |
7016 | let Inst{9-5} = Rn; | |
7017 | let Inst{4-0} = Rd; | |
7018 | } | |
7019 | ||
7020 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
7021 | class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm, | |
7022 | RegisterClass regtype1, RegisterClass regtype2, | |
7023 | Operand immtype, string asm, list<dag> pattern> | |
7024 | : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm), | |
7025 | asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>, | |
7026 | Sched<[WriteV]> { | |
7027 | bits<5> Rd; | |
7028 | bits<5> Rn; | |
7029 | bits<7> imm; | |
7030 | let Inst{31-30} = 0b01; | |
7031 | let Inst{29} = U; | |
7032 | let Inst{28-23} = 0b111110; | |
7033 | let Inst{22-16} = fixed_imm; | |
7034 | let Inst{15-11} = opc; | |
7035 | let Inst{10} = 1; | |
7036 | let Inst{9-5} = Rn; | |
7037 | let Inst{4-0} = Rd; | |
7038 | } | |
7039 | ||
7040 | ||
7041 | multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> { | |
7042 | def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?}, | |
7043 | FPR32, FPR32, vecshiftR32, asm, []> { | |
7044 | let Inst{20-16} = imm{4-0}; | |
7045 | } | |
7046 | ||
7047 | def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?}, | |
7048 | FPR64, FPR64, vecshiftR64, asm, []> { | |
7049 | let Inst{21-16} = imm{5-0}; | |
7050 | } | |
7051 | } | |
7052 | ||
7053 | multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm, | |
7054 | SDPatternOperator OpNode> { | |
7055 | def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?}, | |
7056 | FPR64, FPR64, vecshiftR64, asm, | |
7057 | [(set (i64 FPR64:$Rd), | |
7058 | (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> { | |
7059 | let Inst{21-16} = imm{5-0}; | |
7060 | } | |
7061 | ||
7062 | def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))), | |
7063 | (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>; | |
7064 | } | |
7065 | ||
7066 | multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm, | |
7067 | SDPatternOperator OpNode = null_frag> { | |
7068 | def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?}, | |
7069 | FPR64, FPR64, vecshiftR64, asm, | |
7070 | [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn), | |
7071 | (i32 vecshiftR64:$imm)))]> { | |
7072 | let Inst{21-16} = imm{5-0}; | |
7073 | } | |
7074 | ||
7075 | def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn), | |
7076 | (i32 vecshiftR64:$imm))), | |
7077 | (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn, | |
7078 | vecshiftR64:$imm)>; | |
7079 | } | |
7080 | ||
7081 | multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm, | |
7082 | SDPatternOperator OpNode> { | |
7083 | def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?}, | |
7084 | FPR64, FPR64, vecshiftL64, asm, | |
7085 | [(set (v1i64 FPR64:$Rd), | |
7086 | (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> { | |
7087 | let Inst{21-16} = imm{5-0}; | |
7088 | } | |
7089 | } | |
7090 | ||
7091 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
7092 | multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> { | |
7093 | def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?}, | |
7094 | FPR64, FPR64, vecshiftL64, asm, []> { | |
7095 | let Inst{21-16} = imm{5-0}; | |
7096 | } | |
7097 | } | |
7098 | ||
7099 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
7100 | multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm, | |
7101 | SDPatternOperator OpNode = null_frag> { | |
7102 | def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?}, | |
7103 | FPR8, FPR16, vecshiftR8, asm, []> { | |
7104 | let Inst{18-16} = imm{2-0}; | |
7105 | } | |
7106 | ||
7107 | def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?}, | |
7108 | FPR16, FPR32, vecshiftR16, asm, []> { | |
7109 | let Inst{19-16} = imm{3-0}; | |
7110 | } | |
7111 | ||
7112 | def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?}, | |
7113 | FPR32, FPR64, vecshiftR32, asm, | |
7114 | [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> { | |
7115 | let Inst{20-16} = imm{4-0}; | |
7116 | } | |
7117 | } | |
7118 | ||
7119 | multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm, | |
7120 | SDPatternOperator OpNode> { | |
7121 | def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?}, | |
7122 | FPR8, FPR8, vecshiftL8, asm, []> { | |
7123 | let Inst{18-16} = imm{2-0}; | |
7124 | } | |
7125 | ||
7126 | def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?}, | |
7127 | FPR16, FPR16, vecshiftL16, asm, []> { | |
7128 | let Inst{19-16} = imm{3-0}; | |
7129 | } | |
7130 | ||
7131 | def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?}, | |
7132 | FPR32, FPR32, vecshiftL32, asm, | |
7133 | [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> { | |
7134 | let Inst{20-16} = imm{4-0}; | |
7135 | } | |
7136 | ||
7137 | def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?}, | |
7138 | FPR64, FPR64, vecshiftL64, asm, | |
7139 | [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> { | |
7140 | let Inst{21-16} = imm{5-0}; | |
7141 | } | |
7142 | ||
7143 | def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))), | |
7144 | (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>; | |
7145 | } | |
7146 | ||
7147 | multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> { | |
7148 | def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?}, | |
7149 | FPR8, FPR8, vecshiftR8, asm, []> { | |
7150 | let Inst{18-16} = imm{2-0}; | |
7151 | } | |
7152 | ||
7153 | def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?}, | |
7154 | FPR16, FPR16, vecshiftR16, asm, []> { | |
7155 | let Inst{19-16} = imm{3-0}; | |
7156 | } | |
7157 | ||
7158 | def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?}, | |
7159 | FPR32, FPR32, vecshiftR32, asm, []> { | |
7160 | let Inst{20-16} = imm{4-0}; | |
7161 | } | |
7162 | ||
7163 | def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?}, | |
7164 | FPR64, FPR64, vecshiftR64, asm, []> { | |
7165 | let Inst{21-16} = imm{5-0}; | |
7166 | } | |
7167 | } | |
7168 | ||
7169 | //---------------------------------------------------------------------------- | |
7170 | // AdvSIMD vector x indexed element | |
7171 | //---------------------------------------------------------------------------- | |
7172 | ||
7173 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
7174 | class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm, | |
7175 | RegisterOperand dst_reg, RegisterOperand src_reg, | |
7176 | Operand immtype, | |
7177 | string asm, string dst_kind, string src_kind, | |
7178 | list<dag> pattern> | |
7179 | : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm), | |
7180 | asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" # | |
7181 | "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>, | |
7182 | Sched<[WriteV]> { | |
7183 | bits<5> Rd; | |
7184 | bits<5> Rn; | |
7185 | let Inst{31} = 0; | |
7186 | let Inst{30} = Q; | |
7187 | let Inst{29} = U; | |
7188 | let Inst{28-23} = 0b011110; | |
7189 | let Inst{22-16} = fixed_imm; | |
7190 | let Inst{15-11} = opc; | |
7191 | let Inst{10} = 1; | |
7192 | let Inst{9-5} = Rn; | |
7193 | let Inst{4-0} = Rd; | |
7194 | } | |
7195 | ||
7196 | let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in | |
7197 | class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm, | |
7198 | RegisterOperand vectype1, RegisterOperand vectype2, | |
7199 | Operand immtype, | |
7200 | string asm, string dst_kind, string src_kind, | |
7201 | list<dag> pattern> | |
7202 | : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm), | |
7203 | asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" # | |
7204 | "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>, | |
7205 | Sched<[WriteV]> { | |
7206 | bits<5> Rd; | |
7207 | bits<5> Rn; | |
7208 | let Inst{31} = 0; | |
7209 | let Inst{30} = Q; | |
7210 | let Inst{29} = U; | |
7211 | let Inst{28-23} = 0b011110; | |
7212 | let Inst{22-16} = fixed_imm; | |
7213 | let Inst{15-11} = opc; | |
7214 | let Inst{10} = 1; | |
7215 | let Inst{9-5} = Rn; | |
7216 | let Inst{4-0} = Rd; | |
7217 | } | |
7218 | ||
7219 | multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm, | |
7220 | Intrinsic OpNode> { | |
7221 | def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?}, | |
7222 | V64, V64, vecshiftR32, | |
7223 | asm, ".2s", ".2s", | |
7224 | [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> { | |
7225 | bits<5> imm; | |
7226 | let Inst{20-16} = imm; | |
7227 | } | |
7228 | ||
7229 | def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?}, | |
7230 | V128, V128, vecshiftR32, | |
7231 | asm, ".4s", ".4s", | |
7232 | [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> { | |
7233 | bits<5> imm; | |
7234 | let Inst{20-16} = imm; | |
7235 | } | |
7236 | ||
7237 | def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?}, | |
7238 | V128, V128, vecshiftR64, | |
7239 | asm, ".2d", ".2d", | |
7240 | [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> { | |
7241 | bits<6> imm; | |
7242 | let Inst{21-16} = imm; | |
7243 | } | |
7244 | } | |
7245 | ||
7246 | multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm, | |
7247 | Intrinsic OpNode> { | |
7248 | def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?}, | |
7249 | V64, V64, vecshiftR32, | |
7250 | asm, ".2s", ".2s", | |
7251 | [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> { | |
7252 | bits<5> imm; | |
7253 | let Inst{20-16} = imm; | |
7254 | } | |
7255 | ||
7256 | def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?}, | |
7257 | V128, V128, vecshiftR32, | |
7258 | asm, ".4s", ".4s", | |
7259 | [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> { | |
7260 | bits<5> imm; | |
7261 | let Inst{20-16} = imm; | |
7262 | } | |
7263 | ||
7264 | def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?}, | |
7265 | V128, V128, vecshiftR64, | |
7266 | asm, ".2d", ".2d", | |
7267 | [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> { | |
7268 | bits<6> imm; | |
7269 | let Inst{21-16} = imm; | |
7270 | } | |
7271 | } | |
7272 | ||
7273 | multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm, | |
7274 | SDPatternOperator OpNode> { | |
7275 | def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?}, | |
7276 | V64, V128, vecshiftR16Narrow, | |
7277 | asm, ".8b", ".8h", | |
7278 | [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> { | |
7279 | bits<3> imm; | |
7280 | let Inst{18-16} = imm; | |
7281 | } | |
7282 | ||
7283 | def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?}, | |
7284 | V128, V128, vecshiftR16Narrow, | |
7285 | asm#"2", ".16b", ".8h", []> { | |
7286 | bits<3> imm; | |
7287 | let Inst{18-16} = imm; | |
7288 | let hasSideEffects = 0; | |
7289 | } | |
7290 | ||
7291 | def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?}, | |
7292 | V64, V128, vecshiftR32Narrow, | |
7293 | asm, ".4h", ".4s", | |
7294 | [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> { | |
7295 | bits<4> imm; | |
7296 | let Inst{19-16} = imm; | |
7297 | } | |
7298 | ||
7299 | def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?}, | |
7300 | V128, V128, vecshiftR32Narrow, | |
7301 | asm#"2", ".8h", ".4s", []> { | |
7302 | bits<4> imm; | |
7303 | let Inst{19-16} = imm; | |
7304 | let hasSideEffects = 0; | |
7305 | } | |
7306 | ||
7307 | def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?}, | |
7308 | V64, V128, vecshiftR64Narrow, | |
7309 | asm, ".2s", ".2d", | |
7310 | [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> { | |
7311 | bits<5> imm; | |
7312 | let Inst{20-16} = imm; | |
7313 | } | |
7314 | ||
7315 | def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?}, | |
7316 | V128, V128, vecshiftR64Narrow, | |
7317 | asm#"2", ".4s", ".2d", []> { | |
7318 | bits<5> imm; | |
7319 | let Inst{20-16} = imm; | |
7320 | let hasSideEffects = 0; | |
7321 | } | |
7322 | ||
7323 | // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions | |
7324 | // themselves, so put them here instead. | |
7325 | ||
7326 | // Patterns involving what's effectively an insert high and a normal | |
7327 | // intrinsic, represented by CONCAT_VECTORS. | |
7328 | def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn), | |
7329 | vecshiftR16Narrow:$imm)), | |
7330 | (!cast<Instruction>(NAME # "v16i8_shift") | |
7331 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), | |
7332 | V128:$Rn, vecshiftR16Narrow:$imm)>; | |
7333 | def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), | |
7334 | vecshiftR32Narrow:$imm)), | |
7335 | (!cast<Instruction>(NAME # "v8i16_shift") | |
7336 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), | |
7337 | V128:$Rn, vecshiftR32Narrow:$imm)>; | |
7338 | def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), | |
7339 | vecshiftR64Narrow:$imm)), | |
7340 | (!cast<Instruction>(NAME # "v4i32_shift") | |
7341 | (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), | |
7342 | V128:$Rn, vecshiftR64Narrow:$imm)>; | |
7343 | } | |
7344 | ||
7345 | multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm, | |
7346 | SDPatternOperator OpNode> { | |
7347 | def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?}, | |
7348 | V64, V64, vecshiftL8, | |
7349 | asm, ".8b", ".8b", | |
7350 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), | |
7351 | (i32 vecshiftL8:$imm)))]> { | |
7352 | bits<3> imm; | |
7353 | let Inst{18-16} = imm; | |
7354 | } | |
7355 | ||
7356 | def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?}, | |
7357 | V128, V128, vecshiftL8, | |
7358 | asm, ".16b", ".16b", | |
7359 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), | |
7360 | (i32 vecshiftL8:$imm)))]> { | |
7361 | bits<3> imm; | |
7362 | let Inst{18-16} = imm; | |
7363 | } | |
7364 | ||
7365 | def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?}, | |
7366 | V64, V64, vecshiftL16, | |
7367 | asm, ".4h", ".4h", | |
7368 | [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), | |
7369 | (i32 vecshiftL16:$imm)))]> { | |
7370 | bits<4> imm; | |
7371 | let Inst{19-16} = imm; | |
7372 | } | |
7373 | ||
7374 | def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?}, | |
7375 | V128, V128, vecshiftL16, | |
7376 | asm, ".8h", ".8h", | |
7377 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), | |
7378 | (i32 vecshiftL16:$imm)))]> { | |
7379 | bits<4> imm; | |
7380 | let Inst{19-16} = imm; | |
7381 | } | |
7382 | ||
7383 | def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?}, | |
7384 | V64, V64, vecshiftL32, | |
7385 | asm, ".2s", ".2s", | |
7386 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), | |
7387 | (i32 vecshiftL32:$imm)))]> { | |
7388 | bits<5> imm; | |
7389 | let Inst{20-16} = imm; | |
7390 | } | |
7391 | ||
7392 | def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?}, | |
7393 | V128, V128, vecshiftL32, | |
7394 | asm, ".4s", ".4s", | |
7395 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), | |
7396 | (i32 vecshiftL32:$imm)))]> { | |
7397 | bits<5> imm; | |
7398 | let Inst{20-16} = imm; | |
7399 | } | |
7400 | ||
7401 | def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?}, | |
7402 | V128, V128, vecshiftL64, | |
7403 | asm, ".2d", ".2d", | |
7404 | [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), | |
7405 | (i32 vecshiftL64:$imm)))]> { | |
7406 | bits<6> imm; | |
7407 | let Inst{21-16} = imm; | |
7408 | } | |
7409 | } | |
7410 | ||
7411 | multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm, | |
7412 | SDPatternOperator OpNode> { | |
7413 | def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?}, | |
7414 | V64, V64, vecshiftR8, | |
7415 | asm, ".8b", ".8b", | |
7416 | [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), | |
7417 | (i32 vecshiftR8:$imm)))]> { | |
7418 | bits<3> imm; | |
7419 | let Inst{18-16} = imm; | |
7420 | } | |
7421 | ||
7422 | def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?}, | |
7423 | V128, V128, vecshiftR8, | |
7424 | asm, ".16b", ".16b", | |
7425 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), | |
7426 | (i32 vecshiftR8:$imm)))]> { | |
7427 | bits<3> imm; | |
7428 | let Inst{18-16} = imm; | |
7429 | } | |
7430 | ||
7431 | def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?}, | |
7432 | V64, V64, vecshiftR16, | |
7433 | asm, ".4h", ".4h", | |
7434 | [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), | |
7435 | (i32 vecshiftR16:$imm)))]> { | |
7436 | bits<4> imm; | |
7437 | let Inst{19-16} = imm; | |
7438 | } | |
7439 | ||
7440 | def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?}, | |
7441 | V128, V128, vecshiftR16, | |
7442 | asm, ".8h", ".8h", | |
7443 | [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), | |
7444 | (i32 vecshiftR16:$imm)))]> { | |
7445 | bits<4> imm; | |
7446 | let Inst{19-16} = imm; | |
7447 | } | |
7448 | ||
7449 | def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?}, | |
7450 | V64, V64, vecshiftR32, | |
7451 | asm, ".2s", ".2s", | |
7452 | [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), | |
7453 | (i32 vecshiftR32:$imm)))]> { | |
7454 | bits<5> imm; | |
7455 | let Inst{20-16} = imm; | |
7456 | } | |
7457 | ||
7458 | def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?}, | |
7459 | V128, V128, vecshiftR32, | |
7460 | asm, ".4s", ".4s", | |
7461 | [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), | |
7462 | (i32 vecshiftR32:$imm)))]> { | |
7463 | bits<5> imm; | |
7464 | let Inst{20-16} = imm; | |
7465 | } | |
7466 | ||
7467 | def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?}, | |
7468 | V128, V128, vecshiftR64, | |
7469 | asm, ".2d", ".2d", | |
7470 | [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), | |
7471 | (i32 vecshiftR64:$imm)))]> { | |
7472 | bits<6> imm; | |
7473 | let Inst{21-16} = imm; | |
7474 | } | |
7475 | } | |
7476 | ||
7477 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
7478 | multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm, | |
7479 | SDPatternOperator OpNode = null_frag> { | |
7480 | def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?}, | |
7481 | V64, V64, vecshiftR8, asm, ".8b", ".8b", | |
7482 | [(set (v8i8 V64:$dst), | |
7483 | (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), | |
7484 | (i32 vecshiftR8:$imm)))]> { | |
7485 | bits<3> imm; | |
7486 | let Inst{18-16} = imm; | |
7487 | } | |
7488 | ||
7489 | def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?}, | |
7490 | V128, V128, vecshiftR8, asm, ".16b", ".16b", | |
7491 | [(set (v16i8 V128:$dst), | |
7492 | (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), | |
7493 | (i32 vecshiftR8:$imm)))]> { | |
7494 | bits<3> imm; | |
7495 | let Inst{18-16} = imm; | |
7496 | } | |
7497 | ||
7498 | def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?}, | |
7499 | V64, V64, vecshiftR16, asm, ".4h", ".4h", | |
7500 | [(set (v4i16 V64:$dst), | |
7501 | (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), | |
7502 | (i32 vecshiftR16:$imm)))]> { | |
7503 | bits<4> imm; | |
7504 | let Inst{19-16} = imm; | |
7505 | } | |
7506 | ||
7507 | def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?}, | |
7508 | V128, V128, vecshiftR16, asm, ".8h", ".8h", | |
7509 | [(set (v8i16 V128:$dst), | |
7510 | (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), | |
7511 | (i32 vecshiftR16:$imm)))]> { | |
7512 | bits<4> imm; | |
7513 | let Inst{19-16} = imm; | |
7514 | } | |
7515 | ||
7516 | def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?}, | |
7517 | V64, V64, vecshiftR32, asm, ".2s", ".2s", | |
7518 | [(set (v2i32 V64:$dst), | |
7519 | (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), | |
7520 | (i32 vecshiftR32:$imm)))]> { | |
7521 | bits<5> imm; | |
7522 | let Inst{20-16} = imm; | |
7523 | } | |
7524 | ||
7525 | def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?}, | |
7526 | V128, V128, vecshiftR32, asm, ".4s", ".4s", | |
7527 | [(set (v4i32 V128:$dst), | |
7528 | (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), | |
7529 | (i32 vecshiftR32:$imm)))]> { | |
7530 | bits<5> imm; | |
7531 | let Inst{20-16} = imm; | |
7532 | } | |
7533 | ||
7534 | def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?}, | |
7535 | V128, V128, vecshiftR64, | |
7536 | asm, ".2d", ".2d", [(set (v2i64 V128:$dst), | |
7537 | (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn), | |
7538 | (i32 vecshiftR64:$imm)))]> { | |
7539 | bits<6> imm; | |
7540 | let Inst{21-16} = imm; | |
7541 | } | |
7542 | } | |
7543 | ||
7544 | multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm, | |
7545 | SDPatternOperator OpNode = null_frag> { | |
7546 | def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?}, | |
7547 | V64, V64, vecshiftL8, | |
7548 | asm, ".8b", ".8b", | |
7549 | [(set (v8i8 V64:$dst), | |
7550 | (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), | |
7551 | (i32 vecshiftL8:$imm)))]> { | |
7552 | bits<3> imm; | |
7553 | let Inst{18-16} = imm; | |
7554 | } | |
7555 | ||
7556 | def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?}, | |
7557 | V128, V128, vecshiftL8, | |
7558 | asm, ".16b", ".16b", | |
7559 | [(set (v16i8 V128:$dst), | |
7560 | (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), | |
7561 | (i32 vecshiftL8:$imm)))]> { | |
7562 | bits<3> imm; | |
7563 | let Inst{18-16} = imm; | |
7564 | } | |
7565 | ||
7566 | def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?}, | |
7567 | V64, V64, vecshiftL16, | |
7568 | asm, ".4h", ".4h", | |
7569 | [(set (v4i16 V64:$dst), | |
7570 | (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), | |
7571 | (i32 vecshiftL16:$imm)))]> { | |
7572 | bits<4> imm; | |
7573 | let Inst{19-16} = imm; | |
7574 | } | |
7575 | ||
7576 | def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?}, | |
7577 | V128, V128, vecshiftL16, | |
7578 | asm, ".8h", ".8h", | |
7579 | [(set (v8i16 V128:$dst), | |
7580 | (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), | |
7581 | (i32 vecshiftL16:$imm)))]> { | |
7582 | bits<4> imm; | |
7583 | let Inst{19-16} = imm; | |
7584 | } | |
7585 | ||
7586 | def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?}, | |
7587 | V64, V64, vecshiftL32, | |
7588 | asm, ".2s", ".2s", | |
7589 | [(set (v2i32 V64:$dst), | |
7590 | (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), | |
7591 | (i32 vecshiftL32:$imm)))]> { | |
7592 | bits<5> imm; | |
7593 | let Inst{20-16} = imm; | |
7594 | } | |
7595 | ||
7596 | def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?}, | |
7597 | V128, V128, vecshiftL32, | |
7598 | asm, ".4s", ".4s", | |
7599 | [(set (v4i32 V128:$dst), | |
7600 | (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), | |
7601 | (i32 vecshiftL32:$imm)))]> { | |
7602 | bits<5> imm; | |
7603 | let Inst{20-16} = imm; | |
7604 | } | |
7605 | ||
7606 | def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?}, | |
7607 | V128, V128, vecshiftL64, | |
7608 | asm, ".2d", ".2d", | |
7609 | [(set (v2i64 V128:$dst), | |
7610 | (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn), | |
7611 | (i32 vecshiftL64:$imm)))]> { | |
7612 | bits<6> imm; | |
7613 | let Inst{21-16} = imm; | |
7614 | } | |
7615 | } | |
7616 | ||
7617 | multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm, | |
7618 | SDPatternOperator OpNode> { | |
7619 | def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?}, | |
7620 | V128, V64, vecshiftL8, asm, ".8h", ".8b", | |
7621 | [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> { | |
7622 | bits<3> imm; | |
7623 | let Inst{18-16} = imm; | |
7624 | } | |
7625 | ||
7626 | def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?}, | |
7627 | V128, V128, vecshiftL8, | |
7628 | asm#"2", ".8h", ".16b", | |
7629 | [(set (v8i16 V128:$Rd), | |
7630 | (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> { | |
7631 | bits<3> imm; | |
7632 | let Inst{18-16} = imm; | |
7633 | } | |
7634 | ||
7635 | def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?}, | |
7636 | V128, V64, vecshiftL16, asm, ".4s", ".4h", | |
7637 | [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> { | |
7638 | bits<4> imm; | |
7639 | let Inst{19-16} = imm; | |
7640 | } | |
7641 | ||
7642 | def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?}, | |
7643 | V128, V128, vecshiftL16, | |
7644 | asm#"2", ".4s", ".8h", | |
7645 | [(set (v4i32 V128:$Rd), | |
7646 | (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> { | |
7647 | ||
7648 | bits<4> imm; | |
7649 | let Inst{19-16} = imm; | |
7650 | } | |
7651 | ||
7652 | def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?}, | |
7653 | V128, V64, vecshiftL32, asm, ".2d", ".2s", | |
7654 | [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> { | |
7655 | bits<5> imm; | |
7656 | let Inst{20-16} = imm; | |
7657 | } | |
7658 | ||
7659 | def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?}, | |
7660 | V128, V128, vecshiftL32, | |
7661 | asm#"2", ".2d", ".4s", | |
7662 | [(set (v2i64 V128:$Rd), | |
7663 | (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> { | |
7664 | bits<5> imm; | |
7665 | let Inst{20-16} = imm; | |
7666 | } | |
7667 | } | |
7668 | ||
7669 | ||
7670 | //--- | |
7671 | // Vector load/store | |
7672 | //--- | |
7673 | // SIMD ldX/stX no-index memory references don't allow the optional | |
7674 | // ", #0" constant and handle post-indexing explicitly, so we use | |
7675 | // a more specialized parse method for them. Otherwise, it's the same as | |
7676 | // the general GPR64sp handling. | |
7677 | ||
7678 | class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size, | |
7679 | string asm, dag oops, dag iops, list<dag> pattern> | |
7680 | : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> { | |
7681 | bits<5> Vt; | |
7682 | bits<5> Rn; | |
7683 | let Inst{31} = 0; | |
7684 | let Inst{30} = Q; | |
7685 | let Inst{29-23} = 0b0011000; | |
7686 | let Inst{22} = L; | |
7687 | let Inst{21-16} = 0b000000; | |
7688 | let Inst{15-12} = opcode; | |
7689 | let Inst{11-10} = size; | |
7690 | let Inst{9-5} = Rn; | |
7691 | let Inst{4-0} = Vt; | |
7692 | } | |
7693 | ||
7694 | class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size, | |
7695 | string asm, dag oops, dag iops> | |
7696 | : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> { | |
7697 | bits<5> Vt; | |
7698 | bits<5> Rn; | |
7699 | bits<5> Xm; | |
7700 | let Inst{31} = 0; | |
7701 | let Inst{30} = Q; | |
7702 | let Inst{29-23} = 0b0011001; | |
7703 | let Inst{22} = L; | |
7704 | let Inst{21} = 0; | |
7705 | let Inst{20-16} = Xm; | |
7706 | let Inst{15-12} = opcode; | |
7707 | let Inst{11-10} = size; | |
7708 | let Inst{9-5} = Rn; | |
7709 | let Inst{4-0} = Vt; | |
7710 | } | |
7711 | ||
7712 | // The immediate form of AdvSIMD post-indexed addressing is encoded with | |
7713 | // register post-index addressing from the zero register. | |
7714 | multiclass SIMDLdStAliases<string asm, string layout, string Count, | |
7715 | int Offset, int Size> { | |
7716 | // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16" | |
7717 | // "ld1\t$Vt, [$Rn], #16" | |
7718 | // may get mapped to | |
7719 | // (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR) | |
7720 | def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset, | |
7721 | (!cast<Instruction>(NAME # Count # "v" # layout # "_POST") | |
7722 | GPR64sp:$Rn, | |
7723 | !cast<RegisterOperand>("VecList" # Count # layout):$Vt, | |
7724 | XZR), 1>; | |
7725 | ||
7726 | // E.g. "ld1.8b { v0, v1 }, [x1], #16" | |
7727 | // "ld1.8b\t$Vt, [$Rn], #16" | |
7728 | // may get mapped to | |
7729 | // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR) | |
7730 | def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset, | |
7731 | (!cast<Instruction>(NAME # Count # "v" # layout # "_POST") | |
7732 | GPR64sp:$Rn, | |
7733 | !cast<RegisterOperand>("VecList" # Count # Size):$Vt, | |
7734 | XZR), 0>; | |
7735 | ||
7736 | // E.g. "ld1.8b { v0, v1 }, [x1]" | |
7737 | // "ld1\t$Vt, [$Rn]" | |
7738 | // may get mapped to | |
7739 | // (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn) | |
7740 | def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]", | |
7741 | (!cast<Instruction>(NAME # Count # "v" # layout) | |
7742 | !cast<RegisterOperand>("VecList" # Count # Size):$Vt, | |
7743 | GPR64sp:$Rn), 0>; | |
7744 | ||
7745 | // E.g. "ld1.8b { v0, v1 }, [x1], x2" | |
7746 | // "ld1\t$Vt, [$Rn], $Xm" | |
7747 | // may get mapped to | |
7748 | // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm) | |
7749 | def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm", | |
7750 | (!cast<Instruction>(NAME # Count # "v" # layout # "_POST") | |
7751 | GPR64sp:$Rn, | |
7752 | !cast<RegisterOperand>("VecList" # Count # Size):$Vt, | |
7753 | !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>; | |
7754 | } | |
7755 | ||
7756 | multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128, | |
7757 | int Offset64, bits<4> opcode> { | |
7758 | let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { | |
7759 | def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm, | |
7760 | (outs !cast<RegisterOperand>(veclist # "16b"):$Vt), | |
7761 | (ins GPR64sp:$Rn), []>; | |
7762 | def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm, | |
7763 | (outs !cast<RegisterOperand>(veclist # "8h"):$Vt), | |
7764 | (ins GPR64sp:$Rn), []>; | |
7765 | def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm, | |
7766 | (outs !cast<RegisterOperand>(veclist # "4s"):$Vt), | |
7767 | (ins GPR64sp:$Rn), []>; | |
7768 | def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm, | |
7769 | (outs !cast<RegisterOperand>(veclist # "2d"):$Vt), | |
7770 | (ins GPR64sp:$Rn), []>; | |
7771 | def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm, | |
7772 | (outs !cast<RegisterOperand>(veclist # "8b"):$Vt), | |
7773 | (ins GPR64sp:$Rn), []>; | |
7774 | def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm, | |
7775 | (outs !cast<RegisterOperand>(veclist # "4h"):$Vt), | |
7776 | (ins GPR64sp:$Rn), []>; | |
7777 | def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm, | |
7778 | (outs !cast<RegisterOperand>(veclist # "2s"):$Vt), | |
7779 | (ins GPR64sp:$Rn), []>; | |
7780 | ||
7781 | ||
7782 | def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm, | |
7783 | (outs GPR64sp:$wback, | |
7784 | !cast<RegisterOperand>(veclist # "16b"):$Vt), | |
7785 | (ins GPR64sp:$Rn, | |
7786 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7787 | def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm, | |
7788 | (outs GPR64sp:$wback, | |
7789 | !cast<RegisterOperand>(veclist # "8h"):$Vt), | |
7790 | (ins GPR64sp:$Rn, | |
7791 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7792 | def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm, | |
7793 | (outs GPR64sp:$wback, | |
7794 | !cast<RegisterOperand>(veclist # "4s"):$Vt), | |
7795 | (ins GPR64sp:$Rn, | |
7796 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7797 | def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm, | |
7798 | (outs GPR64sp:$wback, | |
7799 | !cast<RegisterOperand>(veclist # "2d"):$Vt), | |
7800 | (ins GPR64sp:$Rn, | |
7801 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7802 | def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm, | |
7803 | (outs GPR64sp:$wback, | |
7804 | !cast<RegisterOperand>(veclist # "8b"):$Vt), | |
7805 | (ins GPR64sp:$Rn, | |
7806 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7807 | def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm, | |
7808 | (outs GPR64sp:$wback, | |
7809 | !cast<RegisterOperand>(veclist # "4h"):$Vt), | |
7810 | (ins GPR64sp:$Rn, | |
7811 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7812 | def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm, | |
7813 | (outs GPR64sp:$wback, | |
7814 | !cast<RegisterOperand>(veclist # "2s"):$Vt), | |
7815 | (ins GPR64sp:$Rn, | |
7816 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7817 | } | |
7818 | ||
7819 | defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>; | |
7820 | defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>; | |
7821 | defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>; | |
7822 | defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>; | |
7823 | defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>; | |
7824 | defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>; | |
7825 | defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>; | |
7826 | } | |
7827 | ||
7828 | // Only ld1/st1 has a v1d version. | |
7829 | multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128, | |
7830 | int Offset64, bits<4> opcode> { | |
7831 | let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in { | |
7832 | def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs), | |
7833 | (ins !cast<RegisterOperand>(veclist # "16b"):$Vt, | |
7834 | GPR64sp:$Rn), []>; | |
7835 | def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs), | |
7836 | (ins !cast<RegisterOperand>(veclist # "8h"):$Vt, | |
7837 | GPR64sp:$Rn), []>; | |
7838 | def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs), | |
7839 | (ins !cast<RegisterOperand>(veclist # "4s"):$Vt, | |
7840 | GPR64sp:$Rn), []>; | |
7841 | def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs), | |
7842 | (ins !cast<RegisterOperand>(veclist # "2d"):$Vt, | |
7843 | GPR64sp:$Rn), []>; | |
7844 | def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs), | |
7845 | (ins !cast<RegisterOperand>(veclist # "8b"):$Vt, | |
7846 | GPR64sp:$Rn), []>; | |
7847 | def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs), | |
7848 | (ins !cast<RegisterOperand>(veclist # "4h"):$Vt, | |
7849 | GPR64sp:$Rn), []>; | |
7850 | def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs), | |
7851 | (ins !cast<RegisterOperand>(veclist # "2s"):$Vt, | |
7852 | GPR64sp:$Rn), []>; | |
7853 | ||
7854 | def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, | |
7855 | (outs GPR64sp:$wback), | |
7856 | (ins !cast<RegisterOperand>(veclist # "16b"):$Vt, | |
7857 | GPR64sp:$Rn, | |
7858 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7859 | def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, | |
7860 | (outs GPR64sp:$wback), | |
7861 | (ins !cast<RegisterOperand>(veclist # "8h"):$Vt, | |
7862 | GPR64sp:$Rn, | |
7863 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7864 | def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, | |
7865 | (outs GPR64sp:$wback), | |
7866 | (ins !cast<RegisterOperand>(veclist # "4s"):$Vt, | |
7867 | GPR64sp:$Rn, | |
7868 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7869 | def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, | |
7870 | (outs GPR64sp:$wback), | |
7871 | (ins !cast<RegisterOperand>(veclist # "2d"):$Vt, | |
7872 | GPR64sp:$Rn, | |
7873 | !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>; | |
7874 | def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, | |
7875 | (outs GPR64sp:$wback), | |
7876 | (ins !cast<RegisterOperand>(veclist # "8b"):$Vt, | |
7877 | GPR64sp:$Rn, | |
7878 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7879 | def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, | |
7880 | (outs GPR64sp:$wback), | |
7881 | (ins !cast<RegisterOperand>(veclist # "4h"):$Vt, | |
7882 | GPR64sp:$Rn, | |
7883 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7884 | def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, | |
7885 | (outs GPR64sp:$wback), | |
7886 | (ins !cast<RegisterOperand>(veclist # "2s"):$Vt, | |
7887 | GPR64sp:$Rn, | |
7888 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7889 | } | |
7890 | ||
7891 | defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>; | |
7892 | defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>; | |
7893 | defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>; | |
7894 | defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>; | |
7895 | defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>; | |
7896 | defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>; | |
7897 | defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>; | |
7898 | } | |
7899 | ||
7900 | multiclass BaseSIMDLd1<string Count, string asm, string veclist, | |
7901 | int Offset128, int Offset64, bits<4> opcode> | |
7902 | : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> { | |
7903 | ||
7904 | // LD1 instructions have extra "1d" variants. | |
7905 | let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { | |
7906 | def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm, | |
7907 | (outs !cast<RegisterOperand>(veclist # "1d"):$Vt), | |
7908 | (ins GPR64sp:$Rn), []>; | |
7909 | ||
7910 | def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm, | |
7911 | (outs GPR64sp:$wback, | |
7912 | !cast<RegisterOperand>(veclist # "1d"):$Vt), | |
7913 | (ins GPR64sp:$Rn, | |
7914 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7915 | } | |
7916 | ||
7917 | defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>; | |
7918 | } | |
7919 | ||
7920 | multiclass BaseSIMDSt1<string Count, string asm, string veclist, | |
7921 | int Offset128, int Offset64, bits<4> opcode> | |
7922 | : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> { | |
7923 | ||
7924 | // ST1 instructions have extra "1d" variants. | |
7925 | let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { | |
7926 | def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs), | |
7927 | (ins !cast<RegisterOperand>(veclist # "1d"):$Vt, | |
7928 | GPR64sp:$Rn), []>; | |
7929 | ||
7930 | def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, | |
7931 | (outs GPR64sp:$wback), | |
7932 | (ins !cast<RegisterOperand>(veclist # "1d"):$Vt, | |
7933 | GPR64sp:$Rn, | |
7934 | !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>; | |
7935 | } | |
7936 | ||
7937 | defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>; | |
7938 | } | |
7939 | ||
7940 | multiclass SIMDLd1Multiple<string asm> { | |
7941 | defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>; | |
7942 | defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>; | |
7943 | defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>; | |
7944 | defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>; | |
7945 | } | |
7946 | ||
7947 | multiclass SIMDSt1Multiple<string asm> { | |
7948 | defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>; | |
7949 | defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>; | |
7950 | defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>; | |
7951 | defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>; | |
7952 | } | |
7953 | ||
7954 | multiclass SIMDLd2Multiple<string asm> { | |
7955 | defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>; | |
7956 | } | |
7957 | ||
7958 | multiclass SIMDSt2Multiple<string asm> { | |
7959 | defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>; | |
7960 | } | |
7961 | ||
7962 | multiclass SIMDLd3Multiple<string asm> { | |
7963 | defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>; | |
7964 | } | |
7965 | ||
7966 | multiclass SIMDSt3Multiple<string asm> { | |
7967 | defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>; | |
7968 | } | |
7969 | ||
7970 | multiclass SIMDLd4Multiple<string asm> { | |
7971 | defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>; | |
7972 | } | |
7973 | ||
7974 | multiclass SIMDSt4Multiple<string asm> { | |
7975 | defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>; | |
7976 | } | |
7977 | ||
7978 | //--- | |
7979 | // AdvSIMD Load/store single-element | |
7980 | //--- | |
7981 | ||
7982 | class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode, | |
7983 | string asm, string operands, string cst, | |
7984 | dag oops, dag iops, list<dag> pattern> | |
7985 | : I<oops, iops, asm, operands, cst, pattern> { | |
7986 | bits<5> Vt; | |
7987 | bits<5> Rn; | |
7988 | let Inst{31} = 0; | |
7989 | let Inst{29-24} = 0b001101; | |
7990 | let Inst{22} = L; | |
7991 | let Inst{21} = R; | |
7992 | let Inst{15-13} = opcode; | |
7993 | let Inst{9-5} = Rn; | |
7994 | let Inst{4-0} = Vt; | |
7995 | } | |
7996 | ||
7997 | class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode, | |
7998 | string asm, string operands, string cst, | |
7999 | dag oops, dag iops, list<dag> pattern> | |
8000 | : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> { | |
8001 | bits<5> Vt; | |
8002 | bits<5> Rn; | |
8003 | let Inst{31} = 0; | |
8004 | let Inst{29-24} = 0b001101; | |
8005 | let Inst{22} = L; | |
8006 | let Inst{21} = R; | |
8007 | let Inst{15-13} = opcode; | |
8008 | let Inst{9-5} = Rn; | |
8009 | let Inst{4-0} = Vt; | |
8010 | } | |
8011 | ||
8012 | ||
8013 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
8014 | class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm, | |
8015 | Operand listtype> | |
8016 | : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "", | |
8017 | (outs listtype:$Vt), (ins GPR64sp:$Rn), | |
8018 | []> { | |
8019 | let Inst{30} = Q; | |
8020 | let Inst{23} = 0; | |
8021 | let Inst{20-16} = 0b00000; | |
8022 | let Inst{12} = S; | |
8023 | let Inst{11-10} = size; | |
8024 | } | |
8025 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
8026 | class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, | |
8027 | string asm, Operand listtype, Operand GPR64pi> | |
8028 | : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm", | |
8029 | "$Rn = $wback", | |
8030 | (outs GPR64sp:$wback, listtype:$Vt), | |
8031 | (ins GPR64sp:$Rn, GPR64pi:$Xm), []> { | |
8032 | bits<5> Xm; | |
8033 | let Inst{30} = Q; | |
8034 | let Inst{23} = 1; | |
8035 | let Inst{20-16} = Xm; | |
8036 | let Inst{12} = S; | |
8037 | let Inst{11-10} = size; | |
8038 | } | |
8039 | ||
8040 | multiclass SIMDLdrAliases<string asm, string layout, string Count, | |
8041 | int Offset, int Size> { | |
8042 | // E.g. "ld1r { v0.8b }, [x1], #1" | |
8043 | // "ld1r.8b\t$Vt, [$Rn], #1" | |
8044 | // may get mapped to | |
8045 | // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR) | |
8046 | def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset, | |
8047 | (!cast<Instruction>(NAME # "v" # layout # "_POST") | |
8048 | GPR64sp:$Rn, | |
8049 | !cast<RegisterOperand>("VecList" # Count # layout):$Vt, | |
8050 | XZR), 1>; | |
8051 | ||
8052 | // E.g. "ld1r.8b { v0 }, [x1], #1" | |
8053 | // "ld1r.8b\t$Vt, [$Rn], #1" | |
8054 | // may get mapped to | |
8055 | // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR) | |
8056 | def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset, | |
8057 | (!cast<Instruction>(NAME # "v" # layout # "_POST") | |
8058 | GPR64sp:$Rn, | |
8059 | !cast<RegisterOperand>("VecList" # Count # Size):$Vt, | |
8060 | XZR), 0>; | |
8061 | ||
8062 | // E.g. "ld1r.8b { v0 }, [x1]" | |
8063 | // "ld1r.8b\t$Vt, [$Rn]" | |
8064 | // may get mapped to | |
8065 | // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn) | |
8066 | def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]", | |
8067 | (!cast<Instruction>(NAME # "v" # layout) | |
8068 | !cast<RegisterOperand>("VecList" # Count # Size):$Vt, | |
8069 | GPR64sp:$Rn), 0>; | |
8070 | ||
8071 | // E.g. "ld1r.8b { v0 }, [x1], x2" | |
8072 | // "ld1r.8b\t$Vt, [$Rn], $Xm" | |
8073 | // may get mapped to | |
8074 | // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm) | |
8075 | def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm", | |
8076 | (!cast<Instruction>(NAME # "v" # layout # "_POST") | |
8077 | GPR64sp:$Rn, | |
8078 | !cast<RegisterOperand>("VecList" # Count # Size):$Vt, | |
8079 | !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>; | |
8080 | } | |
8081 | ||
8082 | multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count, | |
8083 | int Offset1, int Offset2, int Offset4, int Offset8> { | |
8084 | def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm, | |
8085 | !cast<Operand>("VecList" # Count # "8b")>; | |
8086 | def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm, | |
8087 | !cast<Operand>("VecList" # Count #"16b")>; | |
8088 | def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm, | |
8089 | !cast<Operand>("VecList" # Count #"4h")>; | |
8090 | def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm, | |
8091 | !cast<Operand>("VecList" # Count #"8h")>; | |
8092 | def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm, | |
8093 | !cast<Operand>("VecList" # Count #"2s")>; | |
8094 | def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm, | |
8095 | !cast<Operand>("VecList" # Count #"4s")>; | |
8096 | def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm, | |
8097 | !cast<Operand>("VecList" # Count #"1d")>; | |
8098 | def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm, | |
8099 | !cast<Operand>("VecList" # Count #"2d")>; | |
8100 | ||
8101 | def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm, | |
8102 | !cast<Operand>("VecList" # Count # "8b"), | |
8103 | !cast<Operand>("GPR64pi" # Offset1)>; | |
8104 | def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm, | |
8105 | !cast<Operand>("VecList" # Count # "16b"), | |
8106 | !cast<Operand>("GPR64pi" # Offset1)>; | |
8107 | def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm, | |
8108 | !cast<Operand>("VecList" # Count # "4h"), | |
8109 | !cast<Operand>("GPR64pi" # Offset2)>; | |
8110 | def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm, | |
8111 | !cast<Operand>("VecList" # Count # "8h"), | |
8112 | !cast<Operand>("GPR64pi" # Offset2)>; | |
8113 | def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm, | |
8114 | !cast<Operand>("VecList" # Count # "2s"), | |
8115 | !cast<Operand>("GPR64pi" # Offset4)>; | |
8116 | def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm, | |
8117 | !cast<Operand>("VecList" # Count # "4s"), | |
8118 | !cast<Operand>("GPR64pi" # Offset4)>; | |
8119 | def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm, | |
8120 | !cast<Operand>("VecList" # Count # "1d"), | |
8121 | !cast<Operand>("GPR64pi" # Offset8)>; | |
8122 | def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm, | |
8123 | !cast<Operand>("VecList" # Count # "2d"), | |
8124 | !cast<Operand>("GPR64pi" # Offset8)>; | |
8125 | ||
8126 | defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>; | |
8127 | defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>; | |
8128 | defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>; | |
8129 | defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>; | |
8130 | defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>; | |
8131 | defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>; | |
8132 | defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>; | |
8133 | defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>; | |
8134 | } | |
8135 | ||
8136 | class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm, | |
8137 | dag oops, dag iops, list<dag> pattern> | |
8138 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops, | |
8139 | pattern> { | |
8140 | // idx encoded in Q:S:size fields. | |
8141 | bits<4> idx; | |
8142 | let Inst{30} = idx{3}; | |
8143 | let Inst{23} = 0; | |
8144 | let Inst{20-16} = 0b00000; | |
8145 | let Inst{12} = idx{2}; | |
8146 | let Inst{11-10} = idx{1-0}; | |
8147 | } | |
8148 | class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm, | |
8149 | dag oops, dag iops, list<dag> pattern> | |
8150 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", | |
8151 | oops, iops, pattern> { | |
8152 | // idx encoded in Q:S:size fields. | |
8153 | bits<4> idx; | |
8154 | let Inst{30} = idx{3}; | |
8155 | let Inst{23} = 0; | |
8156 | let Inst{20-16} = 0b00000; | |
8157 | let Inst{12} = idx{2}; | |
8158 | let Inst{11-10} = idx{1-0}; | |
8159 | } | |
8160 | class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm, | |
8161 | dag oops, dag iops> | |
8162 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8163 | "$Rn = $wback", oops, iops, []> { | |
8164 | // idx encoded in Q:S:size fields. | |
8165 | bits<4> idx; | |
8166 | bits<5> Xm; | |
8167 | let Inst{30} = idx{3}; | |
8168 | let Inst{23} = 1; | |
8169 | let Inst{20-16} = Xm; | |
8170 | let Inst{12} = idx{2}; | |
8171 | let Inst{11-10} = idx{1-0}; | |
8172 | } | |
8173 | class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm, | |
8174 | dag oops, dag iops> | |
8175 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8176 | "$Rn = $wback", oops, iops, []> { | |
8177 | // idx encoded in Q:S:size fields. | |
8178 | bits<4> idx; | |
8179 | bits<5> Xm; | |
8180 | let Inst{30} = idx{3}; | |
8181 | let Inst{23} = 1; | |
8182 | let Inst{20-16} = Xm; | |
8183 | let Inst{12} = idx{2}; | |
8184 | let Inst{11-10} = idx{1-0}; | |
8185 | } | |
8186 | ||
8187 | class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm, | |
8188 | dag oops, dag iops, list<dag> pattern> | |
8189 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops, | |
8190 | pattern> { | |
8191 | // idx encoded in Q:S:size<1> fields. | |
8192 | bits<3> idx; | |
8193 | let Inst{30} = idx{2}; | |
8194 | let Inst{23} = 0; | |
8195 | let Inst{20-16} = 0b00000; | |
8196 | let Inst{12} = idx{1}; | |
8197 | let Inst{11} = idx{0}; | |
8198 | let Inst{10} = size; | |
8199 | } | |
8200 | class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm, | |
8201 | dag oops, dag iops, list<dag> pattern> | |
8202 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", | |
8203 | oops, iops, pattern> { | |
8204 | // idx encoded in Q:S:size<1> fields. | |
8205 | bits<3> idx; | |
8206 | let Inst{30} = idx{2}; | |
8207 | let Inst{23} = 0; | |
8208 | let Inst{20-16} = 0b00000; | |
8209 | let Inst{12} = idx{1}; | |
8210 | let Inst{11} = idx{0}; | |
8211 | let Inst{10} = size; | |
8212 | } | |
8213 | ||
8214 | class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm, | |
8215 | dag oops, dag iops> | |
8216 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8217 | "$Rn = $wback", oops, iops, []> { | |
8218 | // idx encoded in Q:S:size<1> fields. | |
8219 | bits<3> idx; | |
8220 | bits<5> Xm; | |
8221 | let Inst{30} = idx{2}; | |
8222 | let Inst{23} = 1; | |
8223 | let Inst{20-16} = Xm; | |
8224 | let Inst{12} = idx{1}; | |
8225 | let Inst{11} = idx{0}; | |
8226 | let Inst{10} = size; | |
8227 | } | |
8228 | class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm, | |
8229 | dag oops, dag iops> | |
8230 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8231 | "$Rn = $wback", oops, iops, []> { | |
8232 | // idx encoded in Q:S:size<1> fields. | |
8233 | bits<3> idx; | |
8234 | bits<5> Xm; | |
8235 | let Inst{30} = idx{2}; | |
8236 | let Inst{23} = 1; | |
8237 | let Inst{20-16} = Xm; | |
8238 | let Inst{12} = idx{1}; | |
8239 | let Inst{11} = idx{0}; | |
8240 | let Inst{10} = size; | |
8241 | } | |
8242 | class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm, | |
8243 | dag oops, dag iops, list<dag> pattern> | |
8244 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops, | |
8245 | pattern> { | |
8246 | // idx encoded in Q:S fields. | |
8247 | bits<2> idx; | |
8248 | let Inst{30} = idx{1}; | |
8249 | let Inst{23} = 0; | |
8250 | let Inst{20-16} = 0b00000; | |
8251 | let Inst{12} = idx{0}; | |
8252 | let Inst{11-10} = size; | |
8253 | } | |
8254 | class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm, | |
8255 | dag oops, dag iops, list<dag> pattern> | |
8256 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", | |
8257 | oops, iops, pattern> { | |
8258 | // idx encoded in Q:S fields. | |
8259 | bits<2> idx; | |
8260 | let Inst{30} = idx{1}; | |
8261 | let Inst{23} = 0; | |
8262 | let Inst{20-16} = 0b00000; | |
8263 | let Inst{12} = idx{0}; | |
8264 | let Inst{11-10} = size; | |
8265 | } | |
8266 | class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size, | |
8267 | string asm, dag oops, dag iops> | |
8268 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8269 | "$Rn = $wback", oops, iops, []> { | |
8270 | // idx encoded in Q:S fields. | |
8271 | bits<2> idx; | |
8272 | bits<5> Xm; | |
8273 | let Inst{30} = idx{1}; | |
8274 | let Inst{23} = 1; | |
8275 | let Inst{20-16} = Xm; | |
8276 | let Inst{12} = idx{0}; | |
8277 | let Inst{11-10} = size; | |
8278 | } | |
8279 | class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size, | |
8280 | string asm, dag oops, dag iops> | |
8281 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8282 | "$Rn = $wback", oops, iops, []> { | |
8283 | // idx encoded in Q:S fields. | |
8284 | bits<2> idx; | |
8285 | bits<5> Xm; | |
8286 | let Inst{30} = idx{1}; | |
8287 | let Inst{23} = 1; | |
8288 | let Inst{20-16} = Xm; | |
8289 | let Inst{12} = idx{0}; | |
8290 | let Inst{11-10} = size; | |
8291 | } | |
8292 | class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm, | |
8293 | dag oops, dag iops, list<dag> pattern> | |
8294 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops, | |
8295 | pattern> { | |
8296 | // idx encoded in Q field. | |
8297 | bits<1> idx; | |
8298 | let Inst{30} = idx; | |
8299 | let Inst{23} = 0; | |
8300 | let Inst{20-16} = 0b00000; | |
8301 | let Inst{12} = 0; | |
8302 | let Inst{11-10} = size; | |
8303 | } | |
8304 | class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm, | |
8305 | dag oops, dag iops, list<dag> pattern> | |
8306 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", | |
8307 | oops, iops, pattern> { | |
8308 | // idx encoded in Q field. | |
8309 | bits<1> idx; | |
8310 | let Inst{30} = idx; | |
8311 | let Inst{23} = 0; | |
8312 | let Inst{20-16} = 0b00000; | |
8313 | let Inst{12} = 0; | |
8314 | let Inst{11-10} = size; | |
8315 | } | |
8316 | class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size, | |
8317 | string asm, dag oops, dag iops> | |
8318 | : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8319 | "$Rn = $wback", oops, iops, []> { | |
8320 | // idx encoded in Q field. | |
8321 | bits<1> idx; | |
8322 | bits<5> Xm; | |
8323 | let Inst{30} = idx; | |
8324 | let Inst{23} = 1; | |
8325 | let Inst{20-16} = Xm; | |
8326 | let Inst{12} = 0; | |
8327 | let Inst{11-10} = size; | |
8328 | } | |
8329 | class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size, | |
8330 | string asm, dag oops, dag iops> | |
8331 | : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm", | |
8332 | "$Rn = $wback", oops, iops, []> { | |
8333 | // idx encoded in Q field. | |
8334 | bits<1> idx; | |
8335 | bits<5> Xm; | |
8336 | let Inst{30} = idx; | |
8337 | let Inst{23} = 1; | |
8338 | let Inst{20-16} = Xm; | |
8339 | let Inst{12} = 0; | |
8340 | let Inst{11-10} = size; | |
8341 | } | |
8342 | ||
8343 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
8344 | multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm, | |
8345 | RegisterOperand listtype, | |
8346 | RegisterOperand GPR64pi> { | |
8347 | def i8 : SIMDLdStSingleBTied<1, R, opcode, asm, | |
8348 | (outs listtype:$dst), | |
8349 | (ins listtype:$Vt, VectorIndexB:$idx, | |
8350 | GPR64sp:$Rn), []>; | |
8351 | ||
8352 | def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm, | |
8353 | (outs GPR64sp:$wback, listtype:$dst), | |
8354 | (ins listtype:$Vt, VectorIndexB:$idx, | |
8355 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8356 | } | |
8357 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
8358 | multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm, | |
8359 | RegisterOperand listtype, | |
8360 | RegisterOperand GPR64pi> { | |
8361 | def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm, | |
8362 | (outs listtype:$dst), | |
8363 | (ins listtype:$Vt, VectorIndexH:$idx, | |
8364 | GPR64sp:$Rn), []>; | |
8365 | ||
8366 | def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm, | |
8367 | (outs GPR64sp:$wback, listtype:$dst), | |
8368 | (ins listtype:$Vt, VectorIndexH:$idx, | |
8369 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8370 | } | |
8371 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
8372 | multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm, | |
8373 | RegisterOperand listtype, | |
8374 | RegisterOperand GPR64pi> { | |
8375 | def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm, | |
8376 | (outs listtype:$dst), | |
8377 | (ins listtype:$Vt, VectorIndexS:$idx, | |
8378 | GPR64sp:$Rn), []>; | |
8379 | ||
8380 | def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm, | |
8381 | (outs GPR64sp:$wback, listtype:$dst), | |
8382 | (ins listtype:$Vt, VectorIndexS:$idx, | |
8383 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8384 | } | |
8385 | let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in | |
8386 | multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm, | |
8387 | RegisterOperand listtype, RegisterOperand GPR64pi> { | |
8388 | def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm, | |
8389 | (outs listtype:$dst), | |
8390 | (ins listtype:$Vt, VectorIndexD:$idx, | |
8391 | GPR64sp:$Rn), []>; | |
8392 | ||
8393 | def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm, | |
8394 | (outs GPR64sp:$wback, listtype:$dst), | |
8395 | (ins listtype:$Vt, VectorIndexD:$idx, | |
8396 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8397 | } | |
8398 | let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
8399 | multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm, | |
8400 | RegisterOperand listtype, RegisterOperand GPR64pi> { | |
8401 | def i8 : SIMDLdStSingleB<0, R, opcode, asm, | |
8402 | (outs), (ins listtype:$Vt, VectorIndexB:$idx, | |
8403 | GPR64sp:$Rn), []>; | |
8404 | ||
8405 | def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm, | |
8406 | (outs GPR64sp:$wback), | |
8407 | (ins listtype:$Vt, VectorIndexB:$idx, | |
8408 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8409 | } | |
8410 | let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
8411 | multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm, | |
8412 | RegisterOperand listtype, RegisterOperand GPR64pi> { | |
8413 | def i16 : SIMDLdStSingleH<0, R, opcode, size, asm, | |
8414 | (outs), (ins listtype:$Vt, VectorIndexH:$idx, | |
8415 | GPR64sp:$Rn), []>; | |
8416 | ||
8417 | def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm, | |
8418 | (outs GPR64sp:$wback), | |
8419 | (ins listtype:$Vt, VectorIndexH:$idx, | |
8420 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8421 | } | |
8422 | let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
8423 | multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm, | |
8424 | RegisterOperand listtype, RegisterOperand GPR64pi> { | |
8425 | def i32 : SIMDLdStSingleS<0, R, opcode, size, asm, | |
8426 | (outs), (ins listtype:$Vt, VectorIndexS:$idx, | |
8427 | GPR64sp:$Rn), []>; | |
8428 | ||
8429 | def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm, | |
8430 | (outs GPR64sp:$wback), | |
8431 | (ins listtype:$Vt, VectorIndexS:$idx, | |
8432 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8433 | } | |
8434 | let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in | |
8435 | multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm, | |
8436 | RegisterOperand listtype, RegisterOperand GPR64pi> { | |
8437 | def i64 : SIMDLdStSingleD<0, R, opcode, size, asm, | |
8438 | (outs), (ins listtype:$Vt, VectorIndexD:$idx, | |
8439 | GPR64sp:$Rn), []>; | |
8440 | ||
8441 | def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm, | |
8442 | (outs GPR64sp:$wback), | |
8443 | (ins listtype:$Vt, VectorIndexD:$idx, | |
8444 | GPR64sp:$Rn, GPR64pi:$Xm)>; | |
8445 | } | |
8446 | ||
8447 | multiclass SIMDLdStSingleAliases<string asm, string layout, string Type, | |
8448 | string Count, int Offset, Operand idxtype> { | |
8449 | // E.g. "ld1 { v0.8b }[0], [x1], #1" | |
8450 | // "ld1\t$Vt, [$Rn], #1" | |
8451 | // may get mapped to | |
8452 | // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR) | |
8453 | def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset, | |
8454 | (!cast<Instruction>(NAME # Type # "_POST") | |
8455 | GPR64sp:$Rn, | |
8456 | !cast<RegisterOperand>("VecList" # Count # layout):$Vt, | |
8457 | idxtype:$idx, XZR), 1>; | |
8458 | ||
8459 | // E.g. "ld1.8b { v0 }[0], [x1], #1" | |
8460 | // "ld1.8b\t$Vt, [$Rn], #1" | |
8461 | // may get mapped to | |
8462 | // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR) | |
8463 | def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset, | |
8464 | (!cast<Instruction>(NAME # Type # "_POST") | |
8465 | GPR64sp:$Rn, | |
8466 | !cast<RegisterOperand>("VecList" # Count # "128"):$Vt, | |
8467 | idxtype:$idx, XZR), 0>; | |
8468 | ||
8469 | // E.g. "ld1.8b { v0 }[0], [x1]" | |
8470 | // "ld1.8b\t$Vt, [$Rn]" | |
8471 | // may get mapped to | |
8472 | // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn) | |
8473 | def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]", | |
8474 | (!cast<Instruction>(NAME # Type) | |
8475 | !cast<RegisterOperand>("VecList" # Count # "128"):$Vt, | |
8476 | idxtype:$idx, GPR64sp:$Rn), 0>; | |
8477 | ||
8478 | // E.g. "ld1.8b { v0 }[0], [x1], x2" | |
8479 | // "ld1.8b\t$Vt, [$Rn], $Xm" | |
8480 | // may get mapped to | |
8481 | // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm) | |
8482 | def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm", | |
8483 | (!cast<Instruction>(NAME # Type # "_POST") | |
8484 | GPR64sp:$Rn, | |
8485 | !cast<RegisterOperand>("VecList" # Count # "128"):$Vt, | |
8486 | idxtype:$idx, | |
8487 | !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>; | |
8488 | } | |
8489 | ||
8490 | multiclass SIMDLdSt1SingleAliases<string asm> { | |
8491 | defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>; | |
8492 | defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>; | |
8493 | defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>; | |
8494 | defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>; | |
8495 | } | |
8496 | ||
8497 | multiclass SIMDLdSt2SingleAliases<string asm> { | |
8498 | defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>; | |
8499 | defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>; | |
8500 | defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>; | |
8501 | defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>; | |
8502 | } | |
8503 | ||
8504 | multiclass SIMDLdSt3SingleAliases<string asm> { | |
8505 | defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>; | |
8506 | defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>; | |
8507 | defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>; | |
8508 | defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>; | |
8509 | } | |
8510 | ||
8511 | multiclass SIMDLdSt4SingleAliases<string asm> { | |
8512 | defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>; | |
8513 | defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>; | |
8514 | defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>; | |
8515 | defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>; | |
8516 | } | |
8517 | } // end of 'let Predicates = [HasNEON]' | |
8518 | ||
8519 | //---------------------------------------------------------------------------- | |
8520 | // Crypto extensions | |
8521 | //---------------------------------------------------------------------------- | |
8522 | ||
8523 | let Predicates = [HasCrypto] in { | |
8524 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
8525 | class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr, | |
8526 | list<dag> pat> | |
8527 | : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>, | |
8528 | Sched<[WriteV]>{ | |
8529 | bits<5> Rd; | |
8530 | bits<5> Rn; | |
8531 | let Inst{31-16} = 0b0100111000101000; | |
8532 | let Inst{15-12} = opc; | |
8533 | let Inst{11-10} = 0b10; | |
8534 | let Inst{9-5} = Rn; | |
8535 | let Inst{4-0} = Rd; | |
8536 | } | |
8537 | ||
8538 | class AESInst<bits<4> opc, string asm, Intrinsic OpNode> | |
8539 | : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "", | |
8540 | [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>; | |
8541 | ||
8542 | class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode> | |
8543 | : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn), | |
8544 | "$Rd = $dst", | |
8545 | [(set (v16i8 V128:$dst), | |
8546 | (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>; | |
8547 | ||
8548 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
8549 | class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind, | |
8550 | dag oops, dag iops, list<dag> pat> | |
8551 | : I<oops, iops, asm, | |
8552 | "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" # | |
8553 | "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>, | |
8554 | Sched<[WriteV]>{ | |
8555 | bits<5> Rd; | |
8556 | bits<5> Rn; | |
8557 | bits<5> Rm; | |
8558 | let Inst{31-21} = 0b01011110000; | |
8559 | let Inst{20-16} = Rm; | |
8560 | let Inst{15} = 0; | |
8561 | let Inst{14-12} = opc; | |
8562 | let Inst{11-10} = 0b00; | |
8563 | let Inst{9-5} = Rn; | |
8564 | let Inst{4-0} = Rd; | |
8565 | } | |
8566 | ||
8567 | class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode> | |
8568 | : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst), | |
8569 | (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm), | |
8570 | [(set (v4i32 FPR128:$dst), | |
8571 | (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn), | |
8572 | (v4i32 V128:$Rm)))]>; | |
8573 | ||
8574 | class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode> | |
8575 | : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst), | |
8576 | (ins V128:$Rd, V128:$Rn, V128:$Rm), | |
8577 | [(set (v4i32 V128:$dst), | |
8578 | (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), | |
8579 | (v4i32 V128:$Rm)))]>; | |
8580 | ||
8581 | class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode> | |
8582 | : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst), | |
8583 | (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm), | |
8584 | [(set (v4i32 FPR128:$dst), | |
8585 | (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn), | |
8586 | (v4i32 V128:$Rm)))]>; | |
8587 | ||
8588 | let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in | |
8589 | class SHA2OpInst<bits<4> opc, string asm, string kind, | |
8590 | string cstr, dag oops, dag iops, | |
8591 | list<dag> pat> | |
8592 | : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind # | |
8593 | "|" # kind # "\t$Rd, $Rn}", cstr, pat>, | |
8594 | Sched<[WriteV]>{ | |
8595 | bits<5> Rd; | |
8596 | bits<5> Rn; | |
8597 | let Inst{31-16} = 0b0101111000101000; | |
8598 | let Inst{15-12} = opc; | |
8599 | let Inst{11-10} = 0b10; | |
8600 | let Inst{9-5} = Rn; | |
8601 | let Inst{4-0} = Rd; | |
8602 | } | |
8603 | ||
8604 | class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode> | |
8605 | : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst), | |
8606 | (ins V128:$Rd, V128:$Rn), | |
8607 | [(set (v4i32 V128:$dst), | |
8608 | (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>; | |
8609 | ||
8610 | class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode> | |
8611 | : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn), | |
8612 | [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>; | |
8613 | } // end of 'let Predicates = [HasCrypto]' | |
8614 | ||
8615 | // Allow the size specifier tokens to be upper case, not just lower. | |
8616 | def : TokenAlias<".8B", ".8b">; | |
8617 | def : TokenAlias<".4H", ".4h">; | |
8618 | def : TokenAlias<".2S", ".2s">; | |
8619 | def : TokenAlias<".1D", ".1d">; | |
8620 | def : TokenAlias<".16B", ".16b">; | |
8621 | def : TokenAlias<".8H", ".8h">; | |
8622 | def : TokenAlias<".4S", ".4s">; | |
8623 | def : TokenAlias<".2D", ".2d">; | |
8624 | def : TokenAlias<".1Q", ".1q">; | |
8625 | def : TokenAlias<".B", ".b">; | |
8626 | def : TokenAlias<".H", ".h">; | |
8627 | def : TokenAlias<".S", ".s">; | |
8628 | def : TokenAlias<".D", ".d">; | |
8629 | def : TokenAlias<".Q", ".q">; |