blob: 51cf79121f82b20e2d0e3dd79041b5b3ac638790 [file] [log] [blame]
Tim Northover00ed9962014-03-29 10:18:08 +00001//===- ARM64InstrFormats.td - ARM64 Instruction Formats ------*- tblgen -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10//===----------------------------------------------------------------------===//
11// Describe ARM64 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.
17class Format<bits<2> val> {
18 bits<2> Value = val;
19}
20
21def PseudoFrm : Format<0>;
22def NormalFrm : Format<1>; // Do we need any others?
23
24// ARM64 Instruction Format
25class ARM64Inst<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).
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;
35 let Namespace = "ARM64";
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)
43class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44 : ARM64Inst<PseudoFrm, cstr> {
45 dag OutOperandList = oops;
46 dag InOperandList = iops;
47 let Pattern = pattern;
48 let isCodeGenOnly = 1;
49}
50
51// Real instructions (have encoding information)
52class EncodedI<string cstr, list<dag> pattern> : ARM64Inst<NormalFrm, cstr> {
53 let Pattern = pattern;
54 let Size = 4;
55}
56
57// Normal instructions
58class 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);
64}
65
66class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
69
70// Helper fragment for an extract of the high portion of a 128-bit vector.
71def extract_high_v16i8 :
72 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73def extract_high_v8i16 :
74 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75def extract_high_v4i32 :
76 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77def extract_high_v2i64 :
78 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80//===----------------------------------------------------------------------===//
81// Asm Operand Classes.
82//
83
84// Shifter operand for arithmetic shifted encodings.
85def ShifterOperand : AsmOperandClass {
86 let Name = "Shifter";
87}
88
89// Shifter operand for mov immediate encodings.
90def MovImm32ShifterOperand : AsmOperandClass {
91 let SuperClasses = [ShifterOperand];
92 let Name = "MovImm32Shifter";
93}
94def MovImm64ShifterOperand : AsmOperandClass {
95 let SuperClasses = [ShifterOperand];
96 let Name = "MovImm64Shifter";
97}
98
99// Shifter operand for arithmetic register shifted encodings.
100def ArithmeticShifterOperand : AsmOperandClass {
101 let SuperClasses = [ShifterOperand];
102 let Name = "ArithmeticShifter";
103}
104
105// Shifter operand for arithmetic shifted encodings for ADD/SUB instructions.
106def AddSubShifterOperand : AsmOperandClass {
107 let SuperClasses = [ArithmeticShifterOperand];
108 let Name = "AddSubShifter";
109}
110
111// Shifter operand for logical vector 128/64-bit shifted encodings.
112def LogicalVecShifterOperand : AsmOperandClass {
113 let SuperClasses = [ShifterOperand];
114 let Name = "LogicalVecShifter";
115}
116def LogicalVecHalfWordShifterOperand : AsmOperandClass {
117 let SuperClasses = [LogicalVecShifterOperand];
118 let Name = "LogicalVecHalfWordShifter";
119}
120
121// The "MSL" shifter on the vector MOVI instruction.
122def MoveVecShifterOperand : AsmOperandClass {
123 let SuperClasses = [ShifterOperand];
124 let Name = "MoveVecShifter";
125}
126
127// Extend operand for arithmetic encodings.
128def ExtendOperand : AsmOperandClass { let Name = "Extend"; }
129def ExtendOperand64 : AsmOperandClass {
130 let SuperClasses = [ExtendOperand];
131 let Name = "Extend64";
132}
133// 'extend' that's a lsl of a 64-bit register.
134def ExtendOperandLSL64 : AsmOperandClass {
135 let SuperClasses = [ExtendOperand];
136 let Name = "ExtendLSL64";
137}
138
139// 8-bit floating-point immediate encodings.
140def FPImmOperand : AsmOperandClass {
141 let Name = "FPImm";
142 let ParserMethod = "tryParseFPImm";
143}
144
145// 8-bit immediate for AdvSIMD where 64-bit values of the form:
146// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
147// are encoded as the eight bit value 'abcdefgh'.
148def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
149
150
151//===----------------------------------------------------------------------===//
152// Operand Definitions.
153//
154
155// ADR[P] instruction labels.
156def AdrpOperand : AsmOperandClass {
157 let Name = "AdrpLabel";
158 let ParserMethod = "tryParseAdrpLabel";
159}
160def adrplabel : Operand<i64> {
161 let EncoderMethod = "getAdrLabelOpValue";
162 let PrintMethod = "printAdrpLabel";
163 let ParserMatchClass = AdrpOperand;
164}
165
166def AdrOperand : AsmOperandClass {
167 let Name = "AdrLabel";
168 let ParserMethod = "tryParseAdrLabel";
169}
170def adrlabel : Operand<i64> {
171 let EncoderMethod = "getAdrLabelOpValue";
172 let ParserMatchClass = AdrOperand;
173}
174
175// simm9 predicate - True if the immediate is in the range [-256, 255].
176def SImm9Operand : AsmOperandClass {
177 let Name = "SImm9";
178 let DiagnosticType = "InvalidMemoryIndexedSImm9";
179}
180def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
181 let ParserMatchClass = SImm9Operand;
182}
183
184// simm7s4 predicate - True if the immediate is a multiple of 4 in the range
185// [-256, 252].
186def SImm7s4Operand : AsmOperandClass {
187 let Name = "SImm7s4";
188 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
189}
190def simm7s4 : Operand<i32> {
191 let ParserMatchClass = SImm7s4Operand;
192 let PrintMethod = "printImmScale4";
193}
194
195// simm7s8 predicate - True if the immediate is a multiple of 8 in the range
196// [-512, 504].
197def SImm7s8Operand : AsmOperandClass {
198 let Name = "SImm7s8";
199 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
200}
201def simm7s8 : Operand<i32> {
202 let ParserMatchClass = SImm7s8Operand;
203 let PrintMethod = "printImmScale8";
204}
205
206// simm7s16 predicate - True if the immediate is a multiple of 16 in the range
207// [-1024, 1008].
208def SImm7s16Operand : AsmOperandClass {
209 let Name = "SImm7s16";
210 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
211}
212def simm7s16 : Operand<i32> {
213 let ParserMatchClass = SImm7s16Operand;
214 let PrintMethod = "printImmScale16";
215}
216
217// imm0_65535 predicate - True if the immediate is in the range [0,65535].
218def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
219def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
220 return ((uint32_t)Imm) < 65536;
221}]> {
222 let ParserMatchClass = Imm0_65535Operand;
223}
224
225def Imm1_8Operand : AsmOperandClass {
226 let Name = "Imm1_8";
227 let DiagnosticType = "InvalidImm1_8";
228}
229def Imm1_16Operand : AsmOperandClass {
230 let Name = "Imm1_16";
231 let DiagnosticType = "InvalidImm1_16";
232}
233def Imm1_32Operand : AsmOperandClass {
234 let Name = "Imm1_32";
235 let DiagnosticType = "InvalidImm1_32";
236}
237def Imm1_64Operand : AsmOperandClass {
238 let Name = "Imm1_64";
239 let DiagnosticType = "InvalidImm1_64";
240}
241
242def MovZSymbolG3AsmOperand : AsmOperandClass {
243 let Name = "MovZSymbolG3";
244 let RenderMethod = "addImmOperands";
245}
246
247def movz_symbol_g3 : Operand<i32> {
248 let ParserMatchClass = MovZSymbolG3AsmOperand;
249}
250
251def MovZSymbolG2AsmOperand : AsmOperandClass {
252 let Name = "MovZSymbolG2";
253 let RenderMethod = "addImmOperands";
254}
255
256def movz_symbol_g2 : Operand<i32> {
257 let ParserMatchClass = MovZSymbolG2AsmOperand;
258}
259
260def MovZSymbolG1AsmOperand : AsmOperandClass {
261 let Name = "MovZSymbolG1";
262 let RenderMethod = "addImmOperands";
263}
264
265def movz_symbol_g1 : Operand<i32> {
266 let ParserMatchClass = MovZSymbolG1AsmOperand;
267}
268
269def MovZSymbolG0AsmOperand : AsmOperandClass {
270 let Name = "MovZSymbolG0";
271 let RenderMethod = "addImmOperands";
272}
273
274def movz_symbol_g0 : Operand<i32> {
275 let ParserMatchClass = MovZSymbolG0AsmOperand;
276}
277
278def MovKSymbolG2AsmOperand : AsmOperandClass {
279 let Name = "MovKSymbolG2";
280 let RenderMethod = "addImmOperands";
281}
282
283def movk_symbol_g2 : Operand<i32> {
284 let ParserMatchClass = MovKSymbolG2AsmOperand;
285}
286
287def MovKSymbolG1AsmOperand : AsmOperandClass {
288 let Name = "MovKSymbolG1";
289 let RenderMethod = "addImmOperands";
290}
291
292def movk_symbol_g1 : Operand<i32> {
293 let ParserMatchClass = MovKSymbolG1AsmOperand;
294}
295
296def MovKSymbolG0AsmOperand : AsmOperandClass {
297 let Name = "MovKSymbolG0";
298 let RenderMethod = "addImmOperands";
299}
300
301def movk_symbol_g0 : Operand<i32> {
302 let ParserMatchClass = MovKSymbolG0AsmOperand;
303}
304
305def fixedpoint32 : Operand<i32> {
306 let EncoderMethod = "getFixedPointScaleOpValue";
307 let DecoderMethod = "DecodeFixedPointScaleImm";
308 let ParserMatchClass = Imm1_32Operand;
309}
310def fixedpoint64 : Operand<i64> {
311 let EncoderMethod = "getFixedPointScaleOpValue";
312 let DecoderMethod = "DecodeFixedPointScaleImm";
313 let ParserMatchClass = Imm1_64Operand;
314}
315
316def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
317 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
318}]> {
319 let EncoderMethod = "getVecShiftR8OpValue";
320 let DecoderMethod = "DecodeVecShiftR8Imm";
321 let ParserMatchClass = Imm1_8Operand;
322}
323def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
324 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
325}]> {
326 let EncoderMethod = "getVecShiftR16OpValue";
327 let DecoderMethod = "DecodeVecShiftR16Imm";
328 let ParserMatchClass = Imm1_16Operand;
329}
330def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
331 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
332}]> {
333 let EncoderMethod = "getVecShiftR16OpValue";
334 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
335 let ParserMatchClass = Imm1_8Operand;
336}
337def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
338 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
339}]> {
340 let EncoderMethod = "getVecShiftR32OpValue";
341 let DecoderMethod = "DecodeVecShiftR32Imm";
342 let ParserMatchClass = Imm1_32Operand;
343}
344def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
345 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
346}]> {
347 let EncoderMethod = "getVecShiftR32OpValue";
348 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
349 let ParserMatchClass = Imm1_16Operand;
350}
351def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
352 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
353}]> {
354 let EncoderMethod = "getVecShiftR64OpValue";
355 let DecoderMethod = "DecodeVecShiftR64Imm";
356 let ParserMatchClass = Imm1_64Operand;
357}
358def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
359 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
360}]> {
361 let EncoderMethod = "getVecShiftR64OpValue";
362 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
363 let ParserMatchClass = Imm1_32Operand;
364}
365
366def Imm0_7Operand : AsmOperandClass { let Name = "Imm0_7"; }
367def Imm0_15Operand : AsmOperandClass { let Name = "Imm0_15"; }
368def Imm0_31Operand : AsmOperandClass { let Name = "Imm0_31"; }
369def Imm0_63Operand : AsmOperandClass { let Name = "Imm0_63"; }
370
371def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
372 return (((uint32_t)Imm) < 8);
373}]> {
374 let EncoderMethod = "getVecShiftL8OpValue";
375 let DecoderMethod = "DecodeVecShiftL8Imm";
376 let ParserMatchClass = Imm0_7Operand;
377}
378def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
379 return (((uint32_t)Imm) < 16);
380}]> {
381 let EncoderMethod = "getVecShiftL16OpValue";
382 let DecoderMethod = "DecodeVecShiftL16Imm";
383 let ParserMatchClass = Imm0_15Operand;
384}
385def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
386 return (((uint32_t)Imm) < 32);
387}]> {
388 let EncoderMethod = "getVecShiftL32OpValue";
389 let DecoderMethod = "DecodeVecShiftL32Imm";
390 let ParserMatchClass = Imm0_31Operand;
391}
392def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
393 return (((uint32_t)Imm) < 64);
394}]> {
395 let EncoderMethod = "getVecShiftL64OpValue";
396 let DecoderMethod = "DecodeVecShiftL64Imm";
397 let ParserMatchClass = Imm0_63Operand;
398}
399
400
401// Crazy immediate formats used by 32-bit and 64-bit logical immediate
402// instructions for splatting repeating bit patterns across the immediate.
403def logical_imm32_XFORM : SDNodeXForm<imm, [{
404 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
405 return CurDAG->getTargetConstant(enc, MVT::i32);
406}]>;
407def logical_imm64_XFORM : SDNodeXForm<imm, [{
408 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
409 return CurDAG->getTargetConstant(enc, MVT::i32);
410}]>;
411
412def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
413def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
414def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
415 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
416}], logical_imm32_XFORM> {
417 let PrintMethod = "printLogicalImm32";
418 let ParserMatchClass = LogicalImm32Operand;
419}
420def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
421 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
422}], logical_imm64_XFORM> {
423 let PrintMethod = "printLogicalImm64";
424 let ParserMatchClass = LogicalImm64Operand;
425}
426
427// imm0_255 predicate - True if the immediate is in the range [0,255].
428def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
429def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
430 return ((uint32_t)Imm) < 256;
431}]> {
432 let ParserMatchClass = Imm0_255Operand;
433}
434
435// imm0_127 predicate - True if the immediate is in the range [0,127]
436def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
437def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
438 return ((uint32_t)Imm) < 128;
439}]> {
440 let ParserMatchClass = Imm0_127Operand;
441}
442
Tim Northover2ad88d32014-04-03 09:26:16 +0000443// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
444// for all shift-amounts.
445
Tim Northover00ed9962014-03-29 10:18:08 +0000446// imm0_63 predicate - True if the immediate is in the range [0,63]
Tim Northover00ed9962014-03-29 10:18:08 +0000447def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
448 return ((uint64_t)Imm) < 64;
449}]> {
450 let ParserMatchClass = Imm0_63Operand;
451}
452
Tim Northover2ad88d32014-04-03 09:26:16 +0000453// imm0_31 predicate - True if the immediate is in the range [0,31]
454def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
Tim Northover00ed9962014-03-29 10:18:08 +0000455 return ((uint64_t)Imm) < 32;
456}]> {
457 let ParserMatchClass = Imm0_31Operand;
458}
459
Tim Northover2ad88d32014-04-03 09:26:16 +0000460// imm0_15 predicate - True if the immediate is in the range [0,15]
461def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
Tim Northover00ed9962014-03-29 10:18:08 +0000462 return ((uint64_t)Imm) < 16;
463}]> {
464 let ParserMatchClass = Imm0_15Operand;
465}
466
Tim Northover00ed9962014-03-29 10:18:08 +0000467// imm0_7 predicate - True if the immediate is in the range [0,7]
Tim Northover2ad88d32014-04-03 09:26:16 +0000468def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
469 return ((uint64_t)Imm) < 8;
Tim Northover00ed9962014-03-29 10:18:08 +0000470}]> {
471 let ParserMatchClass = Imm0_7Operand;
472}
473
474// An arithmetic shifter operand:
475// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
476// {5-0} - imm6
477def arith_shift : Operand<i32> {
478 let PrintMethod = "printShifter";
479 let ParserMatchClass = ArithmeticShifterOperand;
480}
481
482class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
483 : Operand<Ty>,
484 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
485 let PrintMethod = "printShiftedRegister";
486 let MIOperandInfo = (ops regclass, arith_shift);
487}
488
489def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
490def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
491
492// An arithmetic shifter operand:
493// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
494// {5-0} - imm6
495def logical_shift : Operand<i32> {
496 let PrintMethod = "printShifter";
497 let ParserMatchClass = ShifterOperand;
498}
499
500class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
501 : Operand<Ty>,
502 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
503 let PrintMethod = "printShiftedRegister";
504 let MIOperandInfo = (ops regclass, logical_shift);
505}
506
507def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
508def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
509
510// A logical vector shifter operand:
511// {7-6} - shift type: 00 = lsl
512// {5-0} - imm6: #0, #8, #16, or #24
513def logical_vec_shift : Operand<i32> {
514 let PrintMethod = "printShifter";
515 let EncoderMethod = "getVecShifterOpValue";
516 let ParserMatchClass = LogicalVecShifterOperand;
517}
518
519// A logical vector half-word shifter operand:
520// {7-6} - shift type: 00 = lsl
521// {5-0} - imm6: #0 or #8
522def logical_vec_hw_shift : Operand<i32> {
523 let PrintMethod = "printShifter";
524 let EncoderMethod = "getVecShifterOpValue";
525 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
526}
527
528// A vector move shifter operand:
529// {0} - imm1: #8 or #16
530def move_vec_shift : Operand<i32> {
531 let PrintMethod = "printShifter";
532 let EncoderMethod = "getMoveVecShifterOpValue";
533 let ParserMatchClass = MoveVecShifterOperand;
534}
535
536// An ADD/SUB immediate shifter operand:
537// {7-6} - shift type: 00 = lsl
538// {5-0} - imm6: #0 or #12
539def addsub_shift : Operand<i32> {
540 let ParserMatchClass = AddSubShifterOperand;
541}
542
543class addsub_shifted_imm<ValueType Ty>
544 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
545 let PrintMethod = "printAddSubImm";
546 let EncoderMethod = "getAddSubImmOpValue";
547 let MIOperandInfo = (ops i32imm, addsub_shift);
548}
549
550def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
551def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
552
553class neg_addsub_shifted_imm<ValueType Ty>
554 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
555 let PrintMethod = "printAddSubImm";
556 let EncoderMethod = "getAddSubImmOpValue";
557 let MIOperandInfo = (ops i32imm, addsub_shift);
558}
559
560def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
561def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
562
563// An extend operand:
564// {5-3} - extend type
565// {2-0} - imm3
566def arith_extend : Operand<i32> {
567 let PrintMethod = "printExtend";
568 let ParserMatchClass = ExtendOperand;
569}
570def arith_extend64 : Operand<i32> {
571 let PrintMethod = "printExtend";
572 let ParserMatchClass = ExtendOperand64;
573}
574
575// 'extend' that's a lsl of a 64-bit register.
576def arith_extendlsl64 : Operand<i32> {
577 let PrintMethod = "printExtend";
578 let ParserMatchClass = ExtendOperandLSL64;
579}
580
581class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
582 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
583 let PrintMethod = "printExtendedRegister";
584 let MIOperandInfo = (ops GPR32, arith_extend);
585}
586
587class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
588 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
589 let PrintMethod = "printExtendedRegister";
590 let MIOperandInfo = (ops GPR32, arith_extend64);
591}
592
593// Floating-point immediate.
594def fpimm32 : Operand<f32>,
595 PatLeaf<(f32 fpimm), [{
596 return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
597 }], SDNodeXForm<fpimm, [{
598 APFloat InVal = N->getValueAPF();
599 uint32_t enc = ARM64_AM::getFP32Imm(InVal);
600 return CurDAG->getTargetConstant(enc, MVT::i32);
601 }]>> {
602 let ParserMatchClass = FPImmOperand;
603 let PrintMethod = "printFPImmOperand";
604}
605def fpimm64 : Operand<f64>,
606 PatLeaf<(f64 fpimm), [{
607 return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
608 }], SDNodeXForm<fpimm, [{
609 APFloat InVal = N->getValueAPF();
610 uint32_t enc = ARM64_AM::getFP64Imm(InVal);
611 return CurDAG->getTargetConstant(enc, MVT::i32);
612 }]>> {
613 let ParserMatchClass = FPImmOperand;
614 let PrintMethod = "printFPImmOperand";
615}
616
617def fpimm8 : Operand<i32> {
618 let ParserMatchClass = FPImmOperand;
619 let PrintMethod = "printFPImmOperand";
620}
621
622def fpimm0 : PatLeaf<(fpimm), [{
623 return N->isExactlyValue(+0.0);
624}]>;
625
626// 8-bit immediate for AdvSIMD where 64-bit values of the form:
627// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
628// are encoded as the eight bit value 'abcdefgh'.
629def simdimmtype10 : Operand<i32>,
630 PatLeaf<(f64 fpimm), [{
631 return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
632 .bitcastToAPInt()
633 .getZExtValue());
634 }], SDNodeXForm<fpimm, [{
635 APFloat InVal = N->getValueAPF();
636 uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
637 .bitcastToAPInt()
638 .getZExtValue());
639 return CurDAG->getTargetConstant(enc, MVT::i32);
640 }]>> {
641 let ParserMatchClass = SIMDImmType10Operand;
642 let PrintMethod = "printSIMDType10Operand";
643}
644
645
646//---
647// Sytem management
648//---
649
650// Base encoding for system instruction operands.
651let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
652class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
653 : I<oops, iops, asm, operands, "", []> {
654 let Inst{31-22} = 0b1101010100;
655 let Inst{21} = L;
656}
657
658// System instructions which do not have an Rt register.
659class SimpleSystemI<bit L, dag iops, string asm, string operands>
660 : BaseSystemI<L, (outs), iops, asm, operands> {
661 let Inst{4-0} = 0b11111;
662}
663
664// System instructions which have an Rt register.
665class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
666 : BaseSystemI<L, oops, iops, asm, operands>,
667 Sched<[WriteSys]> {
668 bits<5> Rt;
669 let Inst{4-0} = Rt;
670}
671
672// Hint instructions that take both a CRm and a 3-bit immediate.
673class HintI<string mnemonic>
674 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
675 Sched<[WriteHint]> {
676 bits <7> imm;
677 let Inst{20-12} = 0b000110010;
678 let Inst{11-5} = imm;
679}
680
681// System instructions taking a single literal operand which encodes into
682// CRm. op2 differentiates the opcodes.
683def BarrierAsmOperand : AsmOperandClass {
684 let Name = "Barrier";
685 let ParserMethod = "tryParseBarrierOperand";
686}
687def barrier_op : Operand<i32> {
688 let PrintMethod = "printBarrierOption";
689 let ParserMatchClass = BarrierAsmOperand;
690}
691class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
692 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
693 Sched<[WriteBarrier]> {
694 bits<4> CRm;
695 let Inst{20-12} = 0b000110011;
696 let Inst{11-8} = CRm;
697 let Inst{7-5} = opc;
698}
699
700// MRS/MSR system instructions.
701def SystemRegisterOperand : AsmOperandClass {
702 let Name = "SystemRegister";
703 let ParserMethod = "tryParseSystemRegister";
704}
705// concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
706def sysreg_op : Operand<i32> {
707 let ParserMatchClass = SystemRegisterOperand;
708 let DecoderMethod = "DecodeSystemRegister";
709 let PrintMethod = "printSystemRegister";
710}
711
712class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins sysreg_op:$systemreg),
713 "mrs", "\t$Rt, $systemreg"> {
714 bits<15> systemreg;
715 let Inst{20} = 1;
716 let Inst{19-5} = systemreg;
717}
718
719// FIXME: Some of these def CPSR, others don't. Best way to model that?
720// Explicitly modeling each of the system register as a register class
721// would do it, but feels like overkill at this point.
722class MSRI : RtSystemI<0, (outs), (ins sysreg_op:$systemreg, GPR64:$Rt),
723 "msr", "\t$systemreg, $Rt"> {
724 bits<15> systemreg;
725 let Inst{20} = 1;
726 let Inst{19-5} = systemreg;
727}
728
729def SystemCPSRFieldOperand : AsmOperandClass {
730 let Name = "SystemCPSRField";
731 let ParserMethod = "tryParseCPSRField";
732}
733def cpsrfield_op : Operand<i32> {
734 let ParserMatchClass = SystemCPSRFieldOperand;
735 let PrintMethod = "printSystemCPSRField";
736}
737
738let Defs = [CPSR] in
739class MSRcpsrI : SimpleSystemI<0, (ins cpsrfield_op:$cpsr_field, imm0_15:$imm),
740 "msr", "\t$cpsr_field, $imm">,
741 Sched<[WriteSys]> {
742 bits<6> cpsrfield;
743 bits<4> imm;
744 let Inst{20-19} = 0b00;
745 let Inst{18-16} = cpsrfield{5-3};
746 let Inst{15-12} = 0b0100;
747 let Inst{11-8} = imm;
748 let Inst{7-5} = cpsrfield{2-0};
749
750 let DecoderMethod = "DecodeSystemCPSRInstruction";
751}
752
753// SYS and SYSL generic system instructions.
754def SysCRAsmOperand : AsmOperandClass {
755 let Name = "SysCR";
756 let ParserMethod = "tryParseSysCROperand";
757}
758
759def sys_cr_op : Operand<i32> {
760 let PrintMethod = "printSysCROperand";
761 let ParserMatchClass = SysCRAsmOperand;
762}
763
764class SystemI<bit L, string asm>
765 : SimpleSystemI<L,
766 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
767 asm, "\t$op1, $Cn, $Cm, $op2">,
768 Sched<[WriteSys]> {
769 bits<3> op1;
770 bits<4> Cn;
771 bits<4> Cm;
772 bits<3> op2;
773 let Inst{20-19} = 0b01;
774 let Inst{18-16} = op1;
775 let Inst{15-12} = Cn;
776 let Inst{11-8} = Cm;
777 let Inst{7-5} = op2;
778}
779
780class SystemXtI<bit L, string asm>
781 : RtSystemI<L, (outs),
782 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
783 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
784 bits<3> op1;
785 bits<4> Cn;
786 bits<4> Cm;
787 bits<3> op2;
788 let Inst{20-19} = 0b01;
789 let Inst{18-16} = op1;
790 let Inst{15-12} = Cn;
791 let Inst{11-8} = Cm;
792 let Inst{7-5} = op2;
793}
794
795class SystemLXtI<bit L, string asm>
796 : RtSystemI<L, (outs),
797 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
798 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
799 bits<3> op1;
800 bits<4> Cn;
801 bits<4> Cm;
802 bits<3> op2;
803 let Inst{20-19} = 0b01;
804 let Inst{18-16} = op1;
805 let Inst{15-12} = Cn;
806 let Inst{11-8} = Cm;
807 let Inst{7-5} = op2;
808}
809
810
811// Branch (register) instructions:
812//
813// case opc of
814// 0001 blr
815// 0000 br
816// 0101 dret
817// 0100 eret
818// 0010 ret
819// otherwise UNDEFINED
820class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
821 string operands, list<dag> pattern>
822 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
823 let Inst{31-25} = 0b1101011;
824 let Inst{24-21} = opc;
825 let Inst{20-16} = 0b11111;
826 let Inst{15-10} = 0b000000;
827 let Inst{4-0} = 0b00000;
828}
829
830class BranchReg<bits<4> opc, string asm, list<dag> pattern>
831 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
832 bits<5> Rn;
833 let Inst{9-5} = Rn;
834}
835
836let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
837class SpecialReturn<bits<4> opc, string asm>
838 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
839 let Inst{9-5} = 0b11111;
840}
841
842//---
843// Conditional branch instruction.
844//---
845// Branch condition code.
846// 4-bit immediate. Pretty-printed as .<cc>
847def dotCcode : Operand<i32> {
848 let PrintMethod = "printDotCondCode";
849}
850
851// Conditional branch target. 19-bit immediate. The low two bits of the target
852// offset are implied zero and so are not part of the immediate.
853def BranchTarget19Operand : AsmOperandClass {
854 let Name = "BranchTarget19";
855}
856def am_brcond : Operand<OtherVT> {
857 let EncoderMethod = "getCondBranchTargetOpValue";
858 let DecoderMethod = "DecodeCondBranchTarget";
859 let PrintMethod = "printAlignedBranchTarget";
860 let ParserMatchClass = BranchTarget19Operand;
861}
862
863class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
864 "b", "$cond\t$target", "",
865 [(ARM64brcond bb:$target, imm:$cond, CPSR)]>,
866 Sched<[WriteBr]> {
867 let isBranch = 1;
868 let isTerminator = 1;
869 let Uses = [CPSR];
870
871 bits<4> cond;
872 bits<19> target;
873 let Inst{31-24} = 0b01010100;
874 let Inst{23-5} = target;
875 let Inst{4} = 0;
876 let Inst{3-0} = cond;
877}
878
879//---
880// Compare-and-branch instructions.
881//---
882class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
883 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
884 asm, "\t$Rt, $target", "",
885 [(node regtype:$Rt, bb:$target)]>,
886 Sched<[WriteBr]> {
887 let isBranch = 1;
888 let isTerminator = 1;
889
890 bits<5> Rt;
891 bits<19> target;
892 let Inst{30-25} = 0b011010;
893 let Inst{24} = op;
894 let Inst{23-5} = target;
895 let Inst{4-0} = Rt;
896}
897
898multiclass CmpBranch<bit op, string asm, SDNode node> {
899 def W : BaseCmpBranch<GPR32, op, asm, node> {
900 let Inst{31} = 0;
901 }
902 def X : BaseCmpBranch<GPR64, op, asm, node> {
903 let Inst{31} = 1;
904 }
905}
906
907//---
908// Test-bit-and-branch instructions.
909//---
910// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
911// the target offset are implied zero and so are not part of the immediate.
912def BranchTarget14Operand : AsmOperandClass {
913 let Name = "BranchTarget14";
914}
915def am_tbrcond : Operand<OtherVT> {
916 let EncoderMethod = "getTestBranchTargetOpValue";
917 let PrintMethod = "printAlignedBranchTarget";
918 let ParserMatchClass = BranchTarget14Operand;
919}
920
921class TestBranch<bit op, string asm, SDNode node>
922 : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
923 asm, "\t$Rt, $bit_off, $target", "",
924 [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
925 Sched<[WriteBr]> {
926 let isBranch = 1;
927 let isTerminator = 1;
928
929 bits<5> Rt;
930 bits<6> bit_off;
931 bits<14> target;
932
933 let Inst{31} = bit_off{5};
934 let Inst{30-25} = 0b011011;
935 let Inst{24} = op;
936 let Inst{23-19} = bit_off{4-0};
937 let Inst{18-5} = target;
938 let Inst{4-0} = Rt;
939
940 let DecoderMethod = "DecodeTestAndBranch";
941}
942
943//---
944// Unconditional branch (immediate) instructions.
945//---
946def BranchTarget26Operand : AsmOperandClass {
947 let Name = "BranchTarget26";
948}
949def am_b_target : Operand<OtherVT> {
950 let EncoderMethod = "getBranchTargetOpValue";
951 let PrintMethod = "printAlignedBranchTarget";
952 let ParserMatchClass = BranchTarget26Operand;
953}
954def am_bl_target : Operand<i64> {
955 let EncoderMethod = "getBranchTargetOpValue";
956 let PrintMethod = "printAlignedBranchTarget";
957 let ParserMatchClass = BranchTarget26Operand;
958}
959
960class BImm<bit op, dag iops, string asm, list<dag> pattern>
961 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
962 bits<26> addr;
963 let Inst{31} = op;
964 let Inst{30-26} = 0b00101;
965 let Inst{25-0} = addr;
966
967 let DecoderMethod = "DecodeUnconditionalBranch";
968}
969
970class BranchImm<bit op, string asm, list<dag> pattern>
971 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
972class CallImm<bit op, string asm, list<dag> pattern>
973 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
974
975//---
976// Basic one-operand data processing instructions.
977//---
978
979let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
980class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
981 SDPatternOperator node>
982 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
983 [(set regtype:$Rd, (node regtype:$Rn))]>,
984 Sched<[WriteI]> {
985 bits<5> Rd;
986 bits<5> Rn;
987
988 let Inst{30-13} = 0b101101011000000000;
989 let Inst{12-10} = opc;
990 let Inst{9-5} = Rn;
991 let Inst{4-0} = Rd;
992}
993
994let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
995multiclass OneOperandData<bits<3> opc, string asm,
996 SDPatternOperator node = null_frag> {
997 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
998 let Inst{31} = 0;
999 }
1000
1001 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1002 let Inst{31} = 1;
1003 }
1004}
1005
1006class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1007 : BaseOneOperandData<opc, GPR32, asm, node> {
1008 let Inst{31} = 0;
1009}
1010
1011class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1012 : BaseOneOperandData<opc, GPR64, asm, node> {
1013 let Inst{31} = 1;
1014}
1015
1016//---
1017// Basic two-operand data processing instructions.
1018//---
1019class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1020 list<dag> pattern>
1021 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1022 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1023 Sched<[WriteI]> {
1024 let Uses = [CPSR];
1025 bits<5> Rd;
1026 bits<5> Rn;
1027 bits<5> Rm;
1028 let Inst{30} = isSub;
1029 let Inst{28-21} = 0b11010000;
1030 let Inst{20-16} = Rm;
1031 let Inst{15-10} = 0;
1032 let Inst{9-5} = Rn;
1033 let Inst{4-0} = Rd;
1034}
1035
1036class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1037 SDNode OpNode>
1038 : BaseBaseAddSubCarry<isSub, regtype, asm,
1039 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR))]>;
1040
1041class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1042 SDNode OpNode>
1043 : BaseBaseAddSubCarry<isSub, regtype, asm,
1044 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR)),
1045 (implicit CPSR)]> {
1046 let Defs = [CPSR];
1047}
1048
1049multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1050 SDNode OpNode, SDNode OpNode_setflags> {
1051 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1052 let Inst{31} = 0;
1053 let Inst{29} = 0;
1054 }
1055 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1056 let Inst{31} = 1;
1057 let Inst{29} = 0;
1058 }
1059
1060 // Sets flags.
1061 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1062 OpNode_setflags> {
1063 let Inst{31} = 0;
1064 let Inst{29} = 1;
1065 }
1066 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1067 OpNode_setflags> {
1068 let Inst{31} = 1;
1069 let Inst{29} = 1;
1070 }
1071}
1072
1073class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1074 SDPatternOperator OpNode>
1075 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1076 asm, "\t$Rd, $Rn, $Rm", "",
1077 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1078 bits<5> Rd;
1079 bits<5> Rn;
1080 bits<5> Rm;
1081 let Inst{30-21} = 0b0011010110;
1082 let Inst{20-16} = Rm;
1083 let Inst{15-14} = 0b00;
1084 let Inst{13-10} = opc;
1085 let Inst{9-5} = Rn;
1086 let Inst{4-0} = Rd;
1087}
1088
1089class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1090 SDPatternOperator OpNode>
1091 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1092 let Inst{10} = isSigned;
1093}
1094
1095multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1096 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1097 Sched<[WriteID32]> {
1098 let Inst{31} = 0;
1099 }
1100 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1101 Sched<[WriteID64]> {
1102 let Inst{31} = 1;
1103 }
1104}
1105
Tim Northover2ad88d32014-04-03 09:26:16 +00001106class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1107 SDPatternOperator OpNode = null_frag>
Tim Northover00ed9962014-03-29 10:18:08 +00001108 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1109 Sched<[WriteIS]> {
1110 let Inst{11-10} = shift_type;
1111}
1112
1113multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
Tim Northover2ad88d32014-04-03 09:26:16 +00001114 def Wr : BaseShift<shift_type, GPR32, asm> {
Tim Northover00ed9962014-03-29 10:18:08 +00001115 let Inst{31} = 0;
1116 }
1117
1118 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1119 let Inst{31} = 1;
1120 }
Tim Northover2ad88d32014-04-03 09:26:16 +00001121
1122 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1123 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1124 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1125
1126 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1127 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1128
1129 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1130 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1131
1132 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1133 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00001134}
1135
1136class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1137 : InstAlias<asm#" $dst, $src1, $src2",
1138 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1139
1140class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1141 RegisterClass addtype, string asm,
1142 list<dag> pattern>
1143 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1144 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1145 bits<5> Rd;
1146 bits<5> Rn;
1147 bits<5> Rm;
1148 bits<5> Ra;
1149 let Inst{30-24} = 0b0011011;
1150 let Inst{23-21} = opc;
1151 let Inst{20-16} = Rm;
1152 let Inst{15} = isSub;
1153 let Inst{14-10} = Ra;
1154 let Inst{9-5} = Rn;
1155 let Inst{4-0} = Rd;
1156}
1157
1158multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1159 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1160 [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1161 Sched<[WriteIM32]> {
1162 let Inst{31} = 0;
1163 }
1164
1165 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1166 [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1167 Sched<[WriteIM64]> {
1168 let Inst{31} = 1;
1169 }
1170}
1171
1172class WideMulAccum<bit isSub, bits<3> opc, string asm,
1173 SDNode AccNode, SDNode ExtNode>
1174 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1175 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1176 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1177 Sched<[WriteIM32]> {
1178 let Inst{31} = 1;
1179}
1180
1181class MulHi<bits<3> opc, string asm, SDNode OpNode>
1182 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1183 asm, "\t$Rd, $Rn, $Rm", "",
1184 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1185 Sched<[WriteIM64]> {
1186 bits<5> Rd;
1187 bits<5> Rn;
1188 bits<5> Rm;
1189 let Inst{31-24} = 0b10011011;
1190 let Inst{23-21} = opc;
1191 let Inst{20-16} = Rm;
1192 let Inst{15-10} = 0b011111;
1193 let Inst{9-5} = Rn;
1194 let Inst{4-0} = Rd;
1195}
1196
1197class MulAccumWAlias<string asm, Instruction inst>
1198 : InstAlias<asm#" $dst, $src1, $src2",
1199 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1200class MulAccumXAlias<string asm, Instruction inst>
1201 : InstAlias<asm#" $dst, $src1, $src2",
1202 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1203class WideMulAccumAlias<string asm, Instruction inst>
1204 : InstAlias<asm#" $dst, $src1, $src2",
1205 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1206
1207class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1208 SDPatternOperator OpNode, string asm>
1209 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1210 asm, "\t$Rd, $Rn, $Rm", "",
1211 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1212 Sched<[WriteISReg]> {
1213 bits<5> Rd;
1214 bits<5> Rn;
1215 bits<5> Rm;
1216
1217 let Inst{31} = sf;
1218 let Inst{30-21} = 0b0011010110;
1219 let Inst{20-16} = Rm;
1220 let Inst{15-13} = 0b010;
1221 let Inst{12} = C;
1222 let Inst{11-10} = sz;
1223 let Inst{9-5} = Rn;
1224 let Inst{4-0} = Rd;
1225}
1226
1227//---
1228// Address generation.
1229//---
1230
1231class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1232 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1233 pattern>,
1234 Sched<[WriteI]> {
1235 bits<5> Xd;
1236 bits<21> label;
1237 let Inst{31} = page;
1238 let Inst{30-29} = label{1-0};
1239 let Inst{28-24} = 0b10000;
1240 let Inst{23-5} = label{20-2};
1241 let Inst{4-0} = Xd;
1242
1243 let DecoderMethod = "DecodeAdrInstruction";
1244}
1245
1246//---
1247// Move immediate.
1248//---
1249
1250def movimm32_imm : Operand<i32> {
1251 let ParserMatchClass = Imm0_65535Operand;
1252 let EncoderMethod = "getMoveWideImmOpValue";
1253}
1254def movimm32_shift : Operand<i32> {
1255 let PrintMethod = "printShifter";
1256 let ParserMatchClass = MovImm32ShifterOperand;
1257}
1258def movimm64_shift : Operand<i32> {
1259 let PrintMethod = "printShifter";
1260 let ParserMatchClass = MovImm64ShifterOperand;
1261}
1262let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1263class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1264 string asm>
1265 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1266 asm, "\t$Rd, $imm$shift", "", []>,
1267 Sched<[WriteImm]> {
1268 bits<5> Rd;
1269 bits<16> imm;
1270 bits<6> shift;
1271 let Inst{30-29} = opc;
1272 let Inst{28-23} = 0b100101;
1273 let Inst{22-21} = shift{5-4};
1274 let Inst{20-5} = imm;
1275 let Inst{4-0} = Rd;
1276
1277 let DecoderMethod = "DecodeMoveImmInstruction";
1278}
1279
1280multiclass MoveImmediate<bits<2> opc, string asm> {
1281 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1282 let Inst{31} = 0;
1283 }
1284
1285 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1286 let Inst{31} = 1;
1287 }
1288}
1289
1290let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1291class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1292 string asm>
1293 : I<(outs regtype:$Rd),
1294 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1295 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1296 Sched<[WriteI]> {
1297 bits<5> Rd;
1298 bits<16> imm;
1299 bits<6> shift;
1300 let Inst{30-29} = opc;
1301 let Inst{28-23} = 0b100101;
1302 let Inst{22-21} = shift{5-4};
1303 let Inst{20-5} = imm;
1304 let Inst{4-0} = Rd;
1305
1306 let DecoderMethod = "DecodeMoveImmInstruction";
1307}
1308
1309multiclass InsertImmediate<bits<2> opc, string asm> {
1310 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1311 let Inst{31} = 0;
1312 }
1313
1314 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1315 let Inst{31} = 1;
1316 }
1317}
1318
1319//---
1320// Add/Subtract
1321//---
1322
1323class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1324 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1325 string asm, SDPatternOperator OpNode>
1326 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1327 asm, "\t$Rd, $Rn, $imm", "",
1328 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1329 Sched<[WriteI]> {
1330 bits<5> Rd;
1331 bits<5> Rn;
1332 bits<14> imm;
1333 let Inst{30} = isSub;
1334 let Inst{29} = setFlags;
1335 let Inst{28-24} = 0b10001;
1336 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1337 let Inst{21-10} = imm{11-0};
1338 let Inst{9-5} = Rn;
1339 let Inst{4-0} = Rd;
1340 let DecoderMethod = "DecodeBaseAddSubImm";
1341}
1342
1343class BaseAddSubRegPseudo<RegisterClass regtype,
1344 SDPatternOperator OpNode>
1345 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1346 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1347 Sched<[WriteI]>;
1348
1349class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1350 arith_shifted_reg shifted_regtype, string asm,
1351 SDPatternOperator OpNode>
1352 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1353 asm, "\t$Rd, $Rn, $Rm", "",
1354 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1355 Sched<[WriteISReg]> {
1356 // The operands are in order to match the 'addr' MI operands, so we
1357 // don't need an encoder method and by-name matching. Just use the default
1358 // in-order handling. Since we're using by-order, make sure the names
1359 // do not match.
1360 bits<5> dst;
1361 bits<5> src1;
1362 bits<5> src2;
1363 bits<8> shift;
1364 let Inst{30} = isSub;
1365 let Inst{29} = setFlags;
1366 let Inst{28-24} = 0b01011;
1367 let Inst{23-22} = shift{7-6};
1368 let Inst{21} = 0;
1369 let Inst{20-16} = src2;
1370 let Inst{15-10} = shift{5-0};
1371 let Inst{9-5} = src1;
1372 let Inst{4-0} = dst;
1373
1374 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1375}
1376
1377class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1378 RegisterClass src1Regtype, Operand src2Regtype,
1379 string asm, SDPatternOperator OpNode>
1380 : I<(outs dstRegtype:$R1),
1381 (ins src1Regtype:$R2, src2Regtype:$R3),
1382 asm, "\t$R1, $R2, $R3", "",
1383 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1384 Sched<[WriteIEReg]> {
1385 bits<5> Rd;
1386 bits<5> Rn;
1387 bits<5> Rm;
1388 bits<6> ext;
1389 let Inst{30} = isSub;
1390 let Inst{29} = setFlags;
1391 let Inst{28-24} = 0b01011;
1392 let Inst{23-21} = 0b001;
1393 let Inst{20-16} = Rm;
1394 let Inst{15-13} = ext{5-3};
1395 let Inst{12-10} = ext{2-0};
1396 let Inst{9-5} = Rn;
1397 let Inst{4-0} = Rd;
1398
1399 let DecoderMethod = "DecodeAddSubERegInstruction";
1400}
1401
1402let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1403class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1404 RegisterClass src1Regtype, RegisterClass src2Regtype,
1405 Operand ext_op, string asm>
1406 : I<(outs dstRegtype:$Rd),
1407 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1408 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1409 Sched<[WriteIEReg]> {
1410 bits<5> Rd;
1411 bits<5> Rn;
1412 bits<5> Rm;
1413 bits<6> ext;
1414 let Inst{30} = isSub;
1415 let Inst{29} = setFlags;
1416 let Inst{28-24} = 0b01011;
1417 let Inst{23-21} = 0b001;
1418 let Inst{20-16} = Rm;
1419 let Inst{15} = ext{5};
1420 let Inst{12-10} = ext{2-0};
1421 let Inst{9-5} = Rn;
1422 let Inst{4-0} = Rd;
1423
1424 let DecoderMethod = "DecodeAddSubERegInstruction";
1425}
1426
1427// Aliases for register+register add/subtract.
1428class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1429 RegisterClass src1Regtype, RegisterClass src2Regtype,
1430 int shiftExt>
1431 : InstAlias<asm#" $dst, $src1, $src2",
1432 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1433 shiftExt)>;
1434
1435multiclass AddSub<bit isSub, string mnemonic,
1436 SDPatternOperator OpNode = null_frag> {
1437 let hasSideEffects = 0 in {
1438 // Add/Subtract immediate
1439 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1440 mnemonic, OpNode> {
1441 let Inst{31} = 0;
1442 }
1443 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1444 mnemonic, OpNode> {
1445 let Inst{31} = 1;
1446 }
1447
1448 // Add/Subtract register - Only used for CodeGen
1449 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1450 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1451
1452 // Add/Subtract shifted register
1453 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1454 OpNode> {
1455 let Inst{31} = 0;
1456 }
1457 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1458 OpNode> {
1459 let Inst{31} = 1;
1460 }
1461 }
1462
1463 // Add/Subtract extended register
1464 let AddedComplexity = 1, hasSideEffects = 0 in {
1465 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1466 arith_extended_reg32<i32>, mnemonic, OpNode> {
1467 let Inst{31} = 0;
1468 }
1469 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1470 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1471 let Inst{31} = 1;
1472 }
1473 }
1474
1475 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1476 arith_extendlsl64, mnemonic> {
1477 // UXTX and SXTX only.
1478 let Inst{14-13} = 0b11;
1479 let Inst{31} = 1;
1480 }
1481
1482 // Register/register aliases with no shift when SP is not used.
1483 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1484 GPR32, GPR32, GPR32, 0>;
1485 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1486 GPR64, GPR64, GPR64, 0>;
1487
1488 // Register/register aliases with no shift when either the destination or
1489 // first source register is SP. This relies on the shifted register aliases
1490 // above matching first in the case when SP is not used.
1491 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1492 GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1493 def : AddSubRegAlias<mnemonic,
1494 !cast<Instruction>(NAME#"Xrx64"),
1495 GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1496}
1497
1498multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1499 let isCompare = 1, Defs = [CPSR] in {
1500 // Add/Subtract immediate
1501 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1502 mnemonic, OpNode> {
1503 let Inst{31} = 0;
1504 }
1505 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1506 mnemonic, OpNode> {
1507 let Inst{31} = 1;
1508 }
1509
1510 // Add/Subtract register
1511 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1512 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1513
1514 // Add/Subtract shifted register
1515 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1516 OpNode> {
1517 let Inst{31} = 0;
1518 }
1519 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1520 OpNode> {
1521 let Inst{31} = 1;
1522 }
1523
1524 // Add/Subtract extended register
1525 let AddedComplexity = 1 in {
1526 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1527 arith_extended_reg32<i32>, mnemonic, OpNode> {
1528 let Inst{31} = 0;
1529 }
1530 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1531 arith_extended_reg32<i64>, mnemonic, OpNode> {
1532 let Inst{31} = 1;
1533 }
1534 }
1535
1536 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1537 arith_extendlsl64, mnemonic> {
1538 // UXTX and SXTX only.
1539 let Inst{14-13} = 0b11;
1540 let Inst{31} = 1;
1541 }
1542 } // Defs = [CPSR]
1543
1544 // Register/register aliases with no shift when SP is not used.
1545 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1546 GPR32, GPR32, GPR32, 0>;
1547 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1548 GPR64, GPR64, GPR64, 0>;
1549
1550 // Register/register aliases with no shift when the first source register
1551 // is SP. This relies on the shifted register aliases above matching first
1552 // in the case when SP is not used.
1553 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1554 GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1555 def : AddSubRegAlias<mnemonic,
1556 !cast<Instruction>(NAME#"Xrx64"),
1557 GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1558}
1559
1560//---
1561// Extract
1562//---
1563def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
Tim Northover2ad88d32014-04-03 09:26:16 +00001564 SDTCisPtrTy<3>]>;
Tim Northover00ed9962014-03-29 10:18:08 +00001565def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1566
1567class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1568 list<dag> patterns>
1569 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1570 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1571 Sched<[WriteExtr, ReadExtrHi]> {
1572 bits<5> Rd;
1573 bits<5> Rn;
1574 bits<5> Rm;
1575 bits<6> imm;
1576
1577 let Inst{30-23} = 0b00100111;
1578 let Inst{21} = 0;
1579 let Inst{20-16} = Rm;
1580 let Inst{15-10} = imm;
1581 let Inst{9-5} = Rn;
1582 let Inst{4-0} = Rd;
1583}
1584
1585multiclass ExtractImm<string asm> {
1586 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1587 [(set GPR32:$Rd,
1588 (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1589 let Inst{31} = 0;
1590 let Inst{22} = 0;
1591 }
1592 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1593 [(set GPR64:$Rd,
1594 (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1595
1596 let Inst{31} = 1;
1597 let Inst{22} = 1;
1598 }
1599}
1600
1601//---
1602// Bitfield
1603//---
1604
1605let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1606class BaseBitfieldImm<bits<2> opc,
1607 RegisterClass regtype, Operand imm_type, string asm>
1608 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1609 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1610 Sched<[WriteIS]> {
1611 bits<5> Rd;
1612 bits<5> Rn;
1613 bits<6> immr;
1614 bits<6> imms;
1615
1616 let Inst{30-29} = opc;
1617 let Inst{28-23} = 0b100110;
1618 let Inst{21-16} = immr;
1619 let Inst{15-10} = imms;
1620 let Inst{9-5} = Rn;
1621 let Inst{4-0} = Rd;
1622}
1623
1624multiclass BitfieldImm<bits<2> opc, string asm> {
1625 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1626 let Inst{31} = 0;
1627 let Inst{22} = 0;
1628 }
1629 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1630 let Inst{31} = 1;
1631 let Inst{22} = 1;
1632 }
1633}
1634
1635let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1636class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1637 RegisterClass regtype, Operand imm_type, string asm>
1638 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1639 imm_type:$imms),
1640 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1641 Sched<[WriteIS]> {
1642 bits<5> Rd;
1643 bits<5> Rn;
1644 bits<6> immr;
1645 bits<6> imms;
1646
1647 let Inst{30-29} = opc;
1648 let Inst{28-23} = 0b100110;
1649 let Inst{21-16} = immr;
1650 let Inst{15-10} = imms;
1651 let Inst{9-5} = Rn;
1652 let Inst{4-0} = Rd;
1653}
1654
1655multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1656 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1657 let Inst{31} = 0;
1658 let Inst{22} = 0;
1659 }
1660 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1661 let Inst{31} = 1;
1662 let Inst{22} = 1;
1663 }
1664}
1665
1666//---
1667// Logical
1668//---
1669
1670// Logical (immediate)
1671class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1672 RegisterClass sregtype, Operand imm_type, string asm,
1673 list<dag> pattern>
1674 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1675 asm, "\t$Rd, $Rn, $imm", "", pattern>,
1676 Sched<[WriteI]> {
1677 bits<5> Rd;
1678 bits<5> Rn;
1679 bits<13> imm;
1680 let Inst{30-29} = opc;
1681 let Inst{28-23} = 0b100100;
1682 let Inst{22} = imm{12};
1683 let Inst{21-16} = imm{11-6};
1684 let Inst{15-10} = imm{5-0};
1685 let Inst{9-5} = Rn;
1686 let Inst{4-0} = Rd;
1687
1688 let DecoderMethod = "DecodeLogicalImmInstruction";
1689}
1690
1691// Logical (shifted register)
1692class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1693 logical_shifted_reg shifted_regtype, string asm,
1694 list<dag> pattern>
1695 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1696 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1697 Sched<[WriteISReg]> {
1698 // The operands are in order to match the 'addr' MI operands, so we
1699 // don't need an encoder method and by-name matching. Just use the default
1700 // in-order handling. Since we're using by-order, make sure the names
1701 // do not match.
1702 bits<5> dst;
1703 bits<5> src1;
1704 bits<5> src2;
1705 bits<8> shift;
1706 let Inst{30-29} = opc;
1707 let Inst{28-24} = 0b01010;
1708 let Inst{23-22} = shift{7-6};
1709 let Inst{21} = N;
1710 let Inst{20-16} = src2;
1711 let Inst{15-10} = shift{5-0};
1712 let Inst{9-5} = src1;
1713 let Inst{4-0} = dst;
1714
1715 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1716}
1717
1718// Aliases for register+register logical instructions.
1719class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1720 : InstAlias<asm#" $dst, $src1, $src2",
1721 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1722
1723let AddedComplexity = 6 in
1724multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1725 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1726 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1727 logical_imm32:$imm))]> {
1728 let Inst{31} = 0;
1729 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1730 }
1731 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1732 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1733 logical_imm64:$imm))]> {
1734 let Inst{31} = 1;
1735 }
1736}
1737
1738multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1739 let isCompare = 1, Defs = [CPSR] in {
1740 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1741 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1742 let Inst{31} = 0;
1743 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1744 }
1745 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1746 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1747 let Inst{31} = 1;
1748 }
1749 } // end Defs = [CPSR]
1750}
1751
1752class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1753 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1754 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1755 Sched<[WriteI]>;
1756
1757// Split from LogicalImm as not all instructions have both.
1758multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1759 SDPatternOperator OpNode> {
1760 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1761 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1762
1763 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1764 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1765 logical_shifted_reg32:$Rm))]> {
1766 let Inst{31} = 0;
1767 }
1768 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1769 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1770 logical_shifted_reg64:$Rm))]> {
1771 let Inst{31} = 1;
1772 }
1773
1774 def : LogicalRegAlias<mnemonic,
1775 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1776 def : LogicalRegAlias<mnemonic,
1777 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1778}
1779
1780// Split from LogicalReg to allow setting CPSR Defs
1781multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic> {
1782 let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1783 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, []>{
1784 let Inst{31} = 0;
1785 }
1786 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, []>{
1787 let Inst{31} = 1;
1788 }
1789 } // Defs = [CPSR]
1790
1791 def : LogicalRegAlias<mnemonic,
1792 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1793 def : LogicalRegAlias<mnemonic,
1794 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1795}
1796
1797//---
1798// Conditionally set flags
1799//---
1800
1801// Condition code.
1802// 4-bit immediate. Pretty-printed as <cc>
1803def ccode : Operand<i32> {
1804 let PrintMethod = "printCondCode";
1805}
1806
1807let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1808class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1809 : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1810 asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1811 Sched<[WriteI]> {
1812 let Uses = [CPSR];
1813 let Defs = [CPSR];
1814
1815 bits<5> Rn;
1816 bits<5> imm;
1817 bits<4> nzcv;
1818 bits<4> cond;
1819
1820 let Inst{30} = op;
1821 let Inst{29-21} = 0b111010010;
1822 let Inst{20-16} = imm;
1823 let Inst{15-12} = cond;
1824 let Inst{11-10} = 0b10;
1825 let Inst{9-5} = Rn;
1826 let Inst{4} = 0b0;
1827 let Inst{3-0} = nzcv;
1828}
1829
1830multiclass CondSetFlagsImm<bit op, string asm> {
1831 def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1832 let Inst{31} = 0;
1833 }
1834 def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1835 let Inst{31} = 1;
1836 }
1837}
1838
1839let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1840class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1841 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1842 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1843 Sched<[WriteI]> {
1844 let Uses = [CPSR];
1845 let Defs = [CPSR];
1846
1847 bits<5> Rn;
1848 bits<5> Rm;
1849 bits<4> nzcv;
1850 bits<4> cond;
1851
1852 let Inst{30} = op;
1853 let Inst{29-21} = 0b111010010;
1854 let Inst{20-16} = Rm;
1855 let Inst{15-12} = cond;
1856 let Inst{11-10} = 0b00;
1857 let Inst{9-5} = Rn;
1858 let Inst{4} = 0b0;
1859 let Inst{3-0} = nzcv;
1860}
1861
1862multiclass CondSetFlagsReg<bit op, string asm> {
1863 def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1864 let Inst{31} = 0;
1865 }
1866 def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1867 let Inst{31} = 1;
1868 }
1869}
1870
1871//---
1872// Conditional select
1873//---
1874
1875class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1876 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1877 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1878 [(set regtype:$Rd,
1879 (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
1880 Sched<[WriteI]> {
1881 let Uses = [CPSR];
1882
1883 bits<5> Rd;
1884 bits<5> Rn;
1885 bits<5> Rm;
1886 bits<4> cond;
1887
1888 let Inst{30} = op;
1889 let Inst{29-21} = 0b011010100;
1890 let Inst{20-16} = Rm;
1891 let Inst{15-12} = cond;
1892 let Inst{11-10} = op2;
1893 let Inst{9-5} = Rn;
1894 let Inst{4-0} = Rd;
1895}
1896
1897multiclass CondSelect<bit op, bits<2> op2, string asm> {
1898 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1899 let Inst{31} = 0;
1900 }
1901 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1902 let Inst{31} = 1;
1903 }
1904}
1905
1906class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1907 PatFrag frag>
1908 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1909 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1910 [(set regtype:$Rd,
1911 (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1912 (i32 imm:$cond), CPSR))]>,
1913 Sched<[WriteI]> {
1914 let Uses = [CPSR];
1915
1916 bits<5> Rd;
1917 bits<5> Rn;
1918 bits<5> Rm;
1919 bits<4> cond;
1920
1921 let Inst{30} = op;
1922 let Inst{29-21} = 0b011010100;
1923 let Inst{20-16} = Rm;
1924 let Inst{15-12} = cond;
1925 let Inst{11-10} = op2;
1926 let Inst{9-5} = Rn;
1927 let Inst{4-0} = Rd;
1928}
1929
1930multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1931 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1932 let Inst{31} = 0;
1933 }
1934 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1935 let Inst{31} = 1;
1936 }
1937}
1938
1939//---
1940// Special Mask Value
1941//---
1942def maski8_or_more : Operand<i32>,
1943 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1944}
1945def maski16_or_more : Operand<i32>,
1946 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
1947}
1948
1949
1950//---
1951// Load/store
1952//---
1953
1954// (unsigned immediate)
1955// Indexed for 8-bit registers. offset is in range [0,4095].
1956def MemoryIndexed8Operand : AsmOperandClass {
1957 let Name = "MemoryIndexed8";
1958 let DiagnosticType = "InvalidMemoryIndexed8";
1959}
1960def am_indexed8 : Operand<i64>,
1961 ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
1962 let PrintMethod = "printAMIndexed8";
1963 let EncoderMethod
1964 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
1965 let ParserMatchClass = MemoryIndexed8Operand;
1966 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1967}
1968
1969// Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
1970// stored as immval/2 (the 12-bit literal that encodes directly into the insn).
1971def MemoryIndexed16Operand : AsmOperandClass {
1972 let Name = "MemoryIndexed16";
1973 let DiagnosticType = "InvalidMemoryIndexed16";
1974}
1975def am_indexed16 : Operand<i64>,
1976 ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
1977 let PrintMethod = "printAMIndexed16";
1978 let EncoderMethod
1979 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
1980 let ParserMatchClass = MemoryIndexed16Operand;
1981 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1982}
1983
1984// Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
1985// stored as immval/4 (the 12-bit literal that encodes directly into the insn).
1986def MemoryIndexed32Operand : AsmOperandClass {
1987 let Name = "MemoryIndexed32";
1988 let DiagnosticType = "InvalidMemoryIndexed32";
1989}
1990def am_indexed32 : Operand<i64>,
1991 ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
1992 let PrintMethod = "printAMIndexed32";
1993 let EncoderMethod
1994 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
1995 let ParserMatchClass = MemoryIndexed32Operand;
1996 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1997}
1998
1999// Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2000// stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2001def MemoryIndexed64Operand : AsmOperandClass {
2002 let Name = "MemoryIndexed64";
2003 let DiagnosticType = "InvalidMemoryIndexed64";
2004}
2005def am_indexed64 : Operand<i64>,
2006 ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2007 let PrintMethod = "printAMIndexed64";
2008 let EncoderMethod
2009 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2010 let ParserMatchClass = MemoryIndexed64Operand;
2011 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2012}
2013
2014// Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2015// stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2016def MemoryIndexed128Operand : AsmOperandClass {
2017 let Name = "MemoryIndexed128";
2018 let DiagnosticType = "InvalidMemoryIndexed128";
2019}
2020def am_indexed128 : Operand<i64>,
2021 ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2022 let PrintMethod = "printAMIndexed128";
2023 let EncoderMethod
2024 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2025 let ParserMatchClass = MemoryIndexed128Operand;
2026 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2027}
2028
2029// No offset.
2030def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2031def am_noindex : Operand<i64>,
2032 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2033 let PrintMethod = "printAMNoIndex";
2034 let ParserMatchClass = MemoryNoIndexOperand;
2035 let MIOperandInfo = (ops GPR64sp:$base);
2036}
2037
2038class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2039 string asm, list<dag> pattern>
2040 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2041 bits<5> dst;
2042
2043 bits<17> addr;
2044 bits<5> base = addr{4-0};
2045 bits<12> offset = addr{16-5};
2046
2047 let Inst{31-30} = sz;
2048 let Inst{29-27} = 0b111;
2049 let Inst{26} = V;
2050 let Inst{25-24} = 0b01;
2051 let Inst{23-22} = opc;
2052 let Inst{21-10} = offset;
2053 let Inst{9-5} = base;
2054 let Inst{4-0} = dst;
2055
2056 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2057}
2058
2059let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2060class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2061 Operand indextype, string asm, list<dag> pattern>
2062 : BaseLoadStoreUI<sz, V, opc,
2063 (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2064 Sched<[WriteLD]>;
2065
2066let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2067class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2068 Operand indextype, string asm, list<dag> pattern>
2069 : BaseLoadStoreUI<sz, V, opc,
2070 (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2071 Sched<[WriteST]>;
2072
2073def PrefetchOperand : AsmOperandClass {
2074 let Name = "Prefetch";
2075 let ParserMethod = "tryParsePrefetch";
2076}
2077def prfop : Operand<i32> {
2078 let PrintMethod = "printPrefetchOp";
2079 let ParserMatchClass = PrefetchOperand;
2080}
2081
2082let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2083class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2084 : BaseLoadStoreUI<sz, V, opc,
2085 (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2086 Sched<[WriteLD]>;
2087
2088//---
2089// Load literal
2090//---
2091
2092let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2093class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2094 : I<(outs regtype:$Rt), (ins am_brcond:$label),
2095 asm, "\t$Rt, $label", "", []>,
2096 Sched<[WriteLD]> {
2097 bits<5> Rt;
2098 bits<19> label;
2099 let Inst{31-30} = opc;
2100 let Inst{29-27} = 0b011;
2101 let Inst{26} = V;
2102 let Inst{25-24} = 0b00;
2103 let Inst{23-5} = label;
2104 let Inst{4-0} = Rt;
2105}
2106
2107let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2108class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2109 : I<(outs), (ins prfop:$Rt, am_brcond:$label),
2110 asm, "\t$Rt, $label", "", pat>,
2111 Sched<[WriteLD]> {
2112 bits<5> Rt;
2113 bits<19> label;
2114 let Inst{31-30} = opc;
2115 let Inst{29-27} = 0b011;
2116 let Inst{26} = V;
2117 let Inst{25-24} = 0b00;
2118 let Inst{23-5} = label;
2119 let Inst{4-0} = Rt;
2120}
2121
2122//---
2123// Load/store register offset
2124//---
2125
2126class MemROAsmOperand<int sz> : AsmOperandClass {
2127 let Name = "MemoryRegisterOffset"#sz;
2128}
2129
2130def MemROAsmOperand8 : MemROAsmOperand<8>;
2131def MemROAsmOperand16 : MemROAsmOperand<16>;
2132def MemROAsmOperand32 : MemROAsmOperand<32>;
2133def MemROAsmOperand64 : MemROAsmOperand<64>;
2134def MemROAsmOperand128 : MemROAsmOperand<128>;
2135
2136class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2137 let PrintMethod = "printMemoryRegOffset"#sz;
2138 let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2139}
2140
2141def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2142 let ParserMatchClass = MemROAsmOperand8;
2143}
2144
2145def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2146 let ParserMatchClass = MemROAsmOperand16;
2147}
2148
2149def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2150 let ParserMatchClass = MemROAsmOperand32;
2151}
2152
2153def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2154 let ParserMatchClass = MemROAsmOperand64;
2155}
2156
2157def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2158 let ParserMatchClass = MemROAsmOperand128;
2159}
2160
2161class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2162 string asm, dag ins, dag outs, list<dag> pat>
2163 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2164 // The operands are in order to match the 'addr' MI operands, so we
2165 // don't need an encoder method and by-name matching. Just use the default
2166 // in-order handling. Since we're using by-order, make sure the names
2167 // do not match.
2168 bits<5> dst;
2169 bits<5> base;
2170 bits<5> offset;
2171 bits<4> extend;
2172 let Inst{31-30} = sz;
2173 let Inst{29-27} = 0b111;
2174 let Inst{26} = V;
2175 let Inst{25-24} = 0b00;
2176 let Inst{23-22} = opc;
2177 let Inst{21} = 1;
2178 let Inst{20-16} = offset;
2179 let Inst{15-13} = extend{3-1};
2180
2181 let Inst{12} = extend{0};
2182 let Inst{11-10} = 0b10;
2183 let Inst{9-5} = base;
2184 let Inst{4-0} = dst;
2185
2186 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2187}
2188
2189class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2190 string asm, list<dag> pat>
2191 : LoadStore8RO<sz, V, opc, regtype, asm,
2192 (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2193 Sched<[WriteLDIdx, ReadAdrBase]>;
2194
2195class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2196 string asm, list<dag> pat>
2197 : LoadStore8RO<sz, V, opc, regtype, asm,
2198 (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2199 Sched<[WriteSTIdx, ReadAdrBase]>;
2200
2201class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2202 string asm, dag ins, dag outs, list<dag> pat>
2203 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2204 // The operands are in order to match the 'addr' MI operands, so we
2205 // don't need an encoder method and by-name matching. Just use the default
2206 // in-order handling. Since we're using by-order, make sure the names
2207 // do not match.
2208 bits<5> dst;
2209 bits<5> base;
2210 bits<5> offset;
2211 bits<4> extend;
2212 let Inst{31-30} = sz;
2213 let Inst{29-27} = 0b111;
2214 let Inst{26} = V;
2215 let Inst{25-24} = 0b00;
2216 let Inst{23-22} = opc;
2217 let Inst{21} = 1;
2218 let Inst{20-16} = offset;
2219 let Inst{15-13} = extend{3-1};
2220
2221 let Inst{12} = extend{0};
2222 let Inst{11-10} = 0b10;
2223 let Inst{9-5} = base;
2224 let Inst{4-0} = dst;
2225
2226 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2227}
2228
2229class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2230 string asm, list<dag> pat>
2231 : LoadStore16RO<sz, V, opc, regtype, asm,
2232 (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2233 Sched<[WriteLDIdx, ReadAdrBase]>;
2234
2235class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2236 string asm, list<dag> pat>
2237 : LoadStore16RO<sz, V, opc, regtype, asm,
2238 (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2239 Sched<[WriteSTIdx, ReadAdrBase]>;
2240
2241class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2242 string asm, dag ins, dag outs, list<dag> pat>
2243 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2244 // The operands are in order to match the 'addr' MI operands, so we
2245 // don't need an encoder method and by-name matching. Just use the default
2246 // in-order handling. Since we're using by-order, make sure the names
2247 // do not match.
2248 bits<5> dst;
2249 bits<5> base;
2250 bits<5> offset;
2251 bits<4> extend;
2252 let Inst{31-30} = sz;
2253 let Inst{29-27} = 0b111;
2254 let Inst{26} = V;
2255 let Inst{25-24} = 0b00;
2256 let Inst{23-22} = opc;
2257 let Inst{21} = 1;
2258 let Inst{20-16} = offset;
2259 let Inst{15-13} = extend{3-1};
2260
2261 let Inst{12} = extend{0};
2262 let Inst{11-10} = 0b10;
2263 let Inst{9-5} = base;
2264 let Inst{4-0} = dst;
2265
2266 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2267}
2268
2269class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2270 string asm, list<dag> pat>
2271 : LoadStore32RO<sz, V, opc, regtype, asm,
2272 (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2273 Sched<[WriteLDIdx, ReadAdrBase]>;
2274
2275class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2276 string asm, list<dag> pat>
2277 : LoadStore32RO<sz, V, opc, regtype, asm,
2278 (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2279 Sched<[WriteSTIdx, ReadAdrBase]>;
2280
2281class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2282 string asm, dag ins, dag outs, list<dag> pat>
2283 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2284 // The operands are in order to match the 'addr' MI operands, so we
2285 // don't need an encoder method and by-name matching. Just use the default
2286 // in-order handling. Since we're using by-order, make sure the names
2287 // do not match.
2288 bits<5> dst;
2289 bits<5> base;
2290 bits<5> offset;
2291 bits<4> extend;
2292 let Inst{31-30} = sz;
2293 let Inst{29-27} = 0b111;
2294 let Inst{26} = V;
2295 let Inst{25-24} = 0b00;
2296 let Inst{23-22} = opc;
2297 let Inst{21} = 1;
2298 let Inst{20-16} = offset;
2299 let Inst{15-13} = extend{3-1};
2300
2301 let Inst{12} = extend{0};
2302 let Inst{11-10} = 0b10;
2303 let Inst{9-5} = base;
2304 let Inst{4-0} = dst;
2305
2306 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2307}
2308
2309let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2310class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2311 string asm, list<dag> pat>
2312 : LoadStore64RO<sz, V, opc, regtype, asm,
2313 (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2314 Sched<[WriteLDIdx, ReadAdrBase]>;
2315
2316let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2317class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2318 string asm, list<dag> pat>
2319 : LoadStore64RO<sz, V, opc, regtype, asm,
2320 (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2321 Sched<[WriteSTIdx, ReadAdrBase]>;
2322
2323
2324class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2325 string asm, dag ins, dag outs, list<dag> pat>
2326 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2327 // The operands are in order to match the 'addr' MI operands, so we
2328 // don't need an encoder method and by-name matching. Just use the default
2329 // in-order handling. Since we're using by-order, make sure the names
2330 // do not match.
2331 bits<5> dst;
2332 bits<5> base;
2333 bits<5> offset;
2334 bits<4> extend;
2335 let Inst{31-30} = sz;
2336 let Inst{29-27} = 0b111;
2337 let Inst{26} = V;
2338 let Inst{25-24} = 0b00;
2339 let Inst{23-22} = opc;
2340 let Inst{21} = 1;
2341 let Inst{20-16} = offset;
2342 let Inst{15-13} = extend{3-1};
2343
2344 let Inst{12} = extend{0};
2345 let Inst{11-10} = 0b10;
2346 let Inst{9-5} = base;
2347 let Inst{4-0} = dst;
2348
2349 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2350}
2351
2352let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2353class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2354 string asm, list<dag> pat>
2355 : LoadStore128RO<sz, V, opc, regtype, asm,
2356 (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2357 Sched<[WriteLDIdx, ReadAdrBase]>;
2358
2359let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2360class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2361 string asm, list<dag> pat>
2362 : LoadStore128RO<sz, V, opc, regtype, asm,
2363 (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2364 Sched<[WriteSTIdx, ReadAdrBase]>;
2365
2366let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2367class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2368 : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2369 "\t$Rt, $addr", "", pat>,
2370 Sched<[WriteLD]> {
2371 // The operands are in order to match the 'addr' MI operands, so we
2372 // don't need an encoder method and by-name matching. Just use the default
2373 // in-order handling. Since we're using by-order, make sure the names
2374 // do not match.
2375 bits<5> dst;
2376 bits<5> base;
2377 bits<5> offset;
2378 bits<4> extend;
2379 let Inst{31-30} = sz;
2380 let Inst{29-27} = 0b111;
2381 let Inst{26} = V;
2382 let Inst{25-24} = 0b00;
2383 let Inst{23-22} = opc;
2384 let Inst{21} = 1;
2385 let Inst{20-16} = offset;
2386 let Inst{15-13} = extend{3-1};
2387
2388 let Inst{12} = extend{0};
2389 let Inst{11-10} = 0b10;
2390 let Inst{9-5} = base;
2391 let Inst{4-0} = dst;
2392
2393 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2394}
2395
2396//---
2397// Load/store unscaled immediate
2398//---
2399
2400def MemoryUnscaledOperand : AsmOperandClass {
2401 let Name = "MemoryUnscaled";
2402 let DiagnosticType = "InvalidMemoryIndexedSImm9";
2403}
2404class am_unscaled_operand : Operand<i64> {
2405 let PrintMethod = "printAMUnscaled";
2406 let ParserMatchClass = MemoryUnscaledOperand;
2407 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2408}
2409def am_unscaled : am_unscaled_operand;
2410def am_unscaled8 : am_unscaled_operand,
2411 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2412def am_unscaled16 : am_unscaled_operand,
2413 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2414def am_unscaled32 : am_unscaled_operand,
2415 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2416def am_unscaled64 : am_unscaled_operand,
2417 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2418def am_unscaled128 : am_unscaled_operand,
2419 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2420
2421class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2422 string asm, list<dag> pattern>
2423 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2424 // The operands are in order to match the 'addr' MI operands, so we
2425 // don't need an encoder method and by-name matching. Just use the default
2426 // in-order handling. Since we're using by-order, make sure the names
2427 // do not match.
2428 bits<5> dst;
2429 bits<5> base;
2430 bits<9> offset;
2431 let Inst{31-30} = sz;
2432 let Inst{29-27} = 0b111;
2433 let Inst{26} = V;
2434 let Inst{25-24} = 0b00;
2435 let Inst{23-22} = opc;
2436 let Inst{21} = 0;
2437 let Inst{20-12} = offset;
2438 let Inst{11-10} = 0b00;
2439 let Inst{9-5} = base;
2440 let Inst{4-0} = dst;
2441
2442 let DecoderMethod = "DecodeSignedLdStInstruction";
2443}
2444
2445let AddedComplexity = 1 in // try this before LoadUI
2446class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2447 Operand amtype, string asm, list<dag> pattern>
2448 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2449 (ins amtype:$addr), asm, pattern>,
2450 Sched<[WriteLD]>;
2451
2452let AddedComplexity = 1 in // try this before StoreUI
2453class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2454 Operand amtype, string asm, list<dag> pattern>
2455 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2456 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2457 Sched<[WriteST]>;
2458
2459let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2460class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2461 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2462 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2463 Sched<[WriteLD]>;
2464
2465//---
2466// Load/store unscaled immediate, unprivileged
2467//---
2468
2469class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2470 dag oops, dag iops, string asm>
2471 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2472 // The operands are in order to match the 'addr' MI operands, so we
2473 // don't need an encoder method and by-name matching. Just use the default
2474 // in-order handling. Since we're using by-order, make sure the names
2475 // do not match.
2476 bits<5> dst;
2477 bits<5> base;
2478 bits<9> offset;
2479 let Inst{31-30} = sz;
2480 let Inst{29-27} = 0b111;
2481 let Inst{26} = V;
2482 let Inst{25-24} = 0b00;
2483 let Inst{23-22} = opc;
2484 let Inst{21} = 0;
2485 let Inst{20-12} = offset;
2486 let Inst{11-10} = 0b10;
2487 let Inst{9-5} = base;
2488 let Inst{4-0} = dst;
2489
2490 let DecoderMethod = "DecodeSignedLdStInstruction";
2491}
2492
2493let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2494class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2495 string asm>
2496 : BaseLoadStoreUnprivileged<sz, V, opc,
2497 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2498 Sched<[WriteLD]>;
2499}
2500
2501let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2502class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2503 string asm>
2504 : BaseLoadStoreUnprivileged<sz, V, opc,
2505 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2506 Sched<[WriteST]>;
2507}
2508
2509//---
2510// Load/store pre-indexed
2511//---
2512
2513class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2514 string asm, string cstr>
2515 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2516 // The operands are in order to match the 'addr' MI operands, so we
2517 // don't need an encoder method and by-name matching. Just use the default
2518 // in-order handling.
2519 bits<5> dst;
2520 bits<5> base;
2521 bits<9> offset;
2522 let Inst{31-30} = sz;
2523 let Inst{29-27} = 0b111;
2524 let Inst{26} = V;
2525 let Inst{25-24} = 0;
2526 let Inst{23-22} = opc;
2527 let Inst{21} = 0;
2528 let Inst{20-12} = offset;
2529 let Inst{11-10} = 0b11;
2530 let Inst{9-5} = base;
2531 let Inst{4-0} = dst;
2532
2533 let DecoderMethod = "DecodeSignedLdStInstruction";
2534}
2535
2536let hasSideEffects = 0 in {
2537let mayStore = 0, mayLoad = 1 in
2538// FIXME: Modeling the write-back of these instructions for isel is tricky.
2539// we need the complex addressing mode for the memory reference, but
2540// we also need the write-back specified as a tied operand to the
2541// base register. That combination does not play nicely with
2542// the asm matcher and friends.
2543class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2544 string asm>
2545 : BaseLoadStorePreIdx<sz, V, opc,
2546 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2547 (ins am_unscaled:$addr), asm, ""/*"$addr.base = $wback"*/>,
2548 Sched<[WriteLD, WriteAdr]>;
2549
2550let mayStore = 1, mayLoad = 0 in
2551class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2552 string asm>
2553 : BaseLoadStorePreIdx<sz, V, opc,
2554 (outs/* GPR64sp:$wback*/),
2555 (ins regtype:$Rt, am_unscaled:$addr),
2556 asm, ""/*"$addr.base = $wback"*/>,
2557 Sched<[WriteAdr, WriteST]>;
2558} // hasSideEffects = 0
2559
2560// ISel pseudo-instructions which have the tied operands. When the MC lowering
2561// logic finally gets smart enough to strip off tied operands that are just
2562// for isel convenience, we can get rid of these pseudos and just reference
2563// the real instructions directly.
2564//
2565// Ironically, also because of the writeback operands, we can't put the
2566// matcher pattern directly on the instruction, but need to define it
2567// separately.
2568//
2569// Loads aren't matched with patterns here at all, but rather in C++
2570// custom lowering.
2571let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2572class LoadPreIdxPseudo<RegisterClass regtype>
2573 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2574 (ins am_noindex:$addr, simm9:$offset), [],
2575 "$addr.base = $wback,@earlyclobber $wback">,
2576 Sched<[WriteLD, WriteAdr]>;
2577class LoadPostIdxPseudo<RegisterClass regtype>
2578 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2579 (ins am_noindex:$addr, simm9:$offset), [],
2580 "$addr.base = $wback,@earlyclobber $wback">,
2581 Sched<[WriteLD, WriteI]>;
2582}
2583multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2584 SDPatternOperator OpNode> {
2585 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2586 def _isel: Pseudo<(outs GPR64sp:$wback),
2587 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2588 "$addr.base = $wback,@earlyclobber $wback">,
2589 Sched<[WriteAdr, WriteST]>;
2590
2591 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2592 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2593 simm9:$offset)>;
2594}
2595
2596//---
2597// Load/store post-indexed
2598//---
2599
2600// (pre-index) load/stores.
2601class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2602 string asm, string cstr>
2603 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2604 // The operands are in order to match the 'addr' MI operands, so we
2605 // don't need an encoder method and by-name matching. Just use the default
2606 // in-order handling.
2607 bits<5> dst;
2608 bits<5> base;
2609 bits<9> offset;
2610 let Inst{31-30} = sz;
2611 let Inst{29-27} = 0b111;
2612 let Inst{26} = V;
2613 let Inst{25-24} = 0b00;
2614 let Inst{23-22} = opc;
2615 let Inst{21} = 0b0;
2616 let Inst{20-12} = offset;
2617 let Inst{11-10} = 0b01;
2618 let Inst{9-5} = base;
2619 let Inst{4-0} = dst;
2620
2621 let DecoderMethod = "DecodeSignedLdStInstruction";
2622}
2623
2624let hasSideEffects = 0 in {
2625let mayStore = 0, mayLoad = 1 in
2626// FIXME: Modeling the write-back of these instructions for isel is tricky.
2627// we need the complex addressing mode for the memory reference, but
2628// we also need the write-back specified as a tied operand to the
2629// base register. That combination does not play nicely with
2630// the asm matcher and friends.
2631class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2632 string asm>
2633 : BaseLoadStorePostIdx<sz, V, opc,
2634 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2635 (ins am_noindex:$addr, simm9:$idx),
2636 asm, ""/*"$addr.base = $wback"*/>,
2637 Sched<[WriteLD, WriteI]>;
2638
2639let mayStore = 1, mayLoad = 0 in
2640class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2641 string asm>
2642 : BaseLoadStorePostIdx<sz, V, opc,
2643 (outs/* GPR64sp:$wback*/),
2644 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2645 asm, ""/*"$addr.base = $wback"*/>,
2646 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2647} // hasSideEffects = 0
2648
2649// ISel pseudo-instructions which have the tied operands. When the MC lowering
2650// logic finally gets smart enough to strip off tied operands that are just
2651// for isel convenience, we can get rid of these pseudos and just reference
2652// the real instructions directly.
2653//
2654// Ironically, also because of the writeback operands, we can't put the
2655// matcher pattern directly on the instruction, but need to define it
2656// separately.
2657multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2658 SDPatternOperator OpNode, Instruction Insn> {
2659 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2660 def _isel: Pseudo<(outs GPR64sp:$wback),
2661 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2662 "$addr.base = $wback,@earlyclobber $wback">,
2663 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2664 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2665
2666 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2667 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2668 simm9:$idx)>;
2669}
2670
2671//---
2672// Load/store pair
2673//---
2674
2675// (indexed, offset)
2676
2677class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2678 string asm>
2679 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2680 // The operands are in order to match the 'addr' MI operands, so we
2681 // don't need an encoder method and by-name matching. Just use the default
2682 // in-order handling. Since we're using by-order, make sure the names
2683 // do not match.
2684 bits<5> dst;
2685 bits<5> dst2;
2686 bits<5> base;
2687 bits<7> offset;
2688 let Inst{31-30} = opc;
2689 let Inst{29-27} = 0b101;
2690 let Inst{26} = V;
2691 let Inst{25-23} = 0b010;
2692 let Inst{22} = L;
2693 let Inst{21-15} = offset;
2694 let Inst{14-10} = dst2;
2695 let Inst{9-5} = base;
2696 let Inst{4-0} = dst;
2697
2698 let DecoderMethod = "DecodePairLdStInstruction";
2699}
2700
2701let hasSideEffects = 0 in {
2702let mayStore = 0, mayLoad = 1 in
2703class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2704 Operand indextype, string asm>
2705 : BaseLoadStorePairOffset<opc, V, 1,
2706 (outs regtype:$Rt, regtype:$Rt2),
2707 (ins indextype:$addr), asm>,
2708 Sched<[WriteLD, WriteLDHi]>;
2709
2710let mayLoad = 0, mayStore = 1 in
2711class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2712 Operand indextype, string asm>
2713 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2714 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2715 asm>,
2716 Sched<[WriteSTP]>;
2717} // hasSideEffects = 0
2718
2719// (pre-indexed)
2720
2721def MemoryIndexed32SImm7 : AsmOperandClass {
2722 let Name = "MemoryIndexed32SImm7";
2723 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2724}
2725def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2726 let PrintMethod = "printAMIndexed32";
2727 let ParserMatchClass = MemoryIndexed32SImm7;
2728 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2729}
2730
2731def MemoryIndexed64SImm7 : AsmOperandClass {
2732 let Name = "MemoryIndexed64SImm7";
2733 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2734}
2735def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2736 let PrintMethod = "printAMIndexed64";
2737 let ParserMatchClass = MemoryIndexed64SImm7;
2738 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2739}
2740
2741def MemoryIndexed128SImm7 : AsmOperandClass {
2742 let Name = "MemoryIndexed128SImm7";
2743 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2744}
2745def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2746 let PrintMethod = "printAMIndexed128";
2747 let ParserMatchClass = MemoryIndexed128SImm7;
2748 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2749}
2750
2751class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2752 string asm>
2753 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2754 // The operands are in order to match the 'addr' MI operands, so we
2755 // don't need an encoder method and by-name matching. Just use the default
2756 // in-order handling. Since we're using by-order, make sure the names
2757 // do not match.
2758 bits<5> dst;
2759 bits<5> dst2;
2760 bits<5> base;
2761 bits<7> offset;
2762 let Inst{31-30} = opc;
2763 let Inst{29-27} = 0b101;
2764 let Inst{26} = V;
2765 let Inst{25-23} = 0b011;
2766 let Inst{22} = L;
2767 let Inst{21-15} = offset;
2768 let Inst{14-10} = dst2;
2769 let Inst{9-5} = base;
2770 let Inst{4-0} = dst;
2771
2772 let DecoderMethod = "DecodePairLdStInstruction";
2773}
2774
2775let hasSideEffects = 0 in {
2776let mayStore = 0, mayLoad = 1 in
2777class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2778 Operand addrmode, string asm>
2779 : BaseLoadStorePairPreIdx<opc, V, 1,
2780 (outs regtype:$Rt, regtype:$Rt2),
2781 (ins addrmode:$addr), asm>,
2782 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2783
2784let mayStore = 1, mayLoad = 0 in
2785class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2786 Operand addrmode, string asm>
2787 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2788 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2789 asm>,
2790 Sched<[WriteAdr, WriteSTP]>;
2791} // hasSideEffects = 0
2792
2793// (post-indexed)
2794
2795class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2796 string asm>
2797 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2798 // The operands are in order to match the 'addr' MI operands, so we
2799 // don't need an encoder method and by-name matching. Just use the default
2800 // in-order handling. Since we're using by-order, make sure the names
2801 // do not match.
2802 bits<5> dst;
2803 bits<5> dst2;
2804 bits<5> base;
2805 bits<7> offset;
2806 let Inst{31-30} = opc;
2807 let Inst{29-27} = 0b101;
2808 let Inst{26} = V;
2809 let Inst{25-23} = 0b001;
2810 let Inst{22} = L;
2811 let Inst{21-15} = offset;
2812 let Inst{14-10} = dst2;
2813 let Inst{9-5} = base;
2814 let Inst{4-0} = dst;
2815
2816 let DecoderMethod = "DecodePairLdStInstruction";
2817}
2818
2819let hasSideEffects = 0 in {
2820let mayStore = 0, mayLoad = 1 in
2821class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2822 Operand idxtype, string asm>
2823 : BaseLoadStorePairPostIdx<opc, V, 1,
2824 (outs regtype:$Rt, regtype:$Rt2),
2825 (ins am_noindex:$addr, idxtype:$idx), asm>,
2826 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2827
2828let mayStore = 1, mayLoad = 0 in
2829class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2830 Operand idxtype, string asm>
2831 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2832 (ins regtype:$Rt, regtype:$Rt2,
2833 am_noindex:$addr, idxtype:$idx),
2834 asm>,
2835 Sched<[WriteAdr, WriteSTP]>;
2836} // hasSideEffects = 0
2837
2838// (no-allocate)
2839
2840class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2841 string asm>
2842 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2843 // The operands are in order to match the 'addr' MI operands, so we
2844 // don't need an encoder method and by-name matching. Just use the default
2845 // in-order handling. Since we're using by-order, make sure the names
2846 // do not match.
2847 bits<5> dst;
2848 bits<5> dst2;
2849 bits<5> base;
2850 bits<7> offset;
2851 let Inst{31-30} = opc;
2852 let Inst{29-27} = 0b101;
2853 let Inst{26} = V;
2854 let Inst{25-23} = 0b000;
2855 let Inst{22} = L;
2856 let Inst{21-15} = offset;
2857 let Inst{14-10} = dst2;
2858 let Inst{9-5} = base;
2859 let Inst{4-0} = dst;
2860
2861 let DecoderMethod = "DecodePairLdStInstruction";
2862}
2863
2864let hasSideEffects = 0 in {
2865let mayStore = 0, mayLoad = 1 in
2866class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2867 Operand indextype, string asm>
2868 : BaseLoadStorePairNoAlloc<opc, V, 1,
2869 (outs regtype:$Rt, regtype:$Rt2),
2870 (ins indextype:$addr), asm>,
2871 Sched<[WriteLD, WriteLDHi]>;
2872
2873let mayStore = 1, mayLoad = 0 in
2874class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2875 Operand indextype, string asm>
2876 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2877 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2878 asm>,
2879 Sched<[WriteSTP]>;
2880} // hasSideEffects = 0
2881
2882//---
2883// Load/store exclusive
2884//---
2885
2886// True exclusive operations write to and/or read from the system's exclusive
2887// monitors, which as far as a compiler is concerned can be modelled as a
2888// random shared memory address. Hence LoadExclusive mayStore.
2889let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2890class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2891 dag oops, dag iops, string asm, string operands>
2892 : I<oops, iops, asm, operands, "", []> {
2893 let Inst{31-30} = sz;
2894 let Inst{29-24} = 0b001000;
2895 let Inst{23} = o2;
2896 let Inst{22} = L;
2897 let Inst{21} = o1;
2898 let Inst{15} = o0;
2899
2900 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2901}
2902
2903// Neither Rs nor Rt2 operands.
2904class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2905 dag oops, dag iops, string asm, string operands>
2906 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2907 bits<5> reg;
2908 bits<5> base;
2909 let Inst{20-16} = 0b11111;
2910 let Inst{14-10} = 0b11111;
2911 let Inst{9-5} = base;
2912 let Inst{4-0} = reg;
2913}
2914
2915// Simple load acquires don't set the exclusive monitor
2916let mayLoad = 1, mayStore = 0 in
2917class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2918 RegisterClass regtype, string asm>
2919 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2920 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2921 Sched<[WriteLD]>;
2922
2923class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2924 RegisterClass regtype, string asm>
2925 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2926 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2927 Sched<[WriteLD]>;
2928
2929class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2930 RegisterClass regtype, string asm>
2931 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2932 (outs regtype:$Rt, regtype:$Rt2),
2933 (ins am_noindex:$addr), asm,
2934 "\t$Rt, $Rt2, $addr">,
2935 Sched<[WriteLD, WriteLDHi]> {
2936 bits<5> dst1;
2937 bits<5> dst2;
2938 bits<5> base;
2939 let Inst{20-16} = 0b11111;
2940 let Inst{14-10} = dst2;
2941 let Inst{9-5} = base;
2942 let Inst{4-0} = dst1;
2943}
2944
2945// Simple store release operations do not check the exclusive monitor.
2946let mayLoad = 0, mayStore = 1 in
2947class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2948 RegisterClass regtype, string asm>
2949 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
2950 (ins regtype:$Rt, am_noindex:$addr),
2951 asm, "\t$Rt, $addr">,
2952 Sched<[WriteST]>;
2953
2954let mayLoad = 1, mayStore = 1 in
2955class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2956 RegisterClass regtype, string asm>
2957 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
2958 (ins regtype:$Rt, am_noindex:$addr),
2959 asm, "\t$Ws, $Rt, $addr">,
2960 Sched<[WriteSTX]> {
2961 bits<5> status;
2962 bits<5> reg;
2963 bits<5> base;
2964 let Inst{20-16} = status;
2965 let Inst{14-10} = 0b11111;
2966 let Inst{9-5} = base;
2967 let Inst{4-0} = reg;
2968
2969 let Constraints = "@earlyclobber $Ws";
2970}
2971
2972class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2973 RegisterClass regtype, string asm>
2974 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2975 (outs GPR32:$Ws),
2976 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
2977 asm, "\t$Ws, $Rt, $Rt2, $addr">,
2978 Sched<[WriteSTX]> {
2979 bits<5> status;
2980 bits<5> dst1;
2981 bits<5> dst2;
2982 bits<5> base;
2983 let Inst{20-16} = status;
2984 let Inst{14-10} = dst2;
2985 let Inst{9-5} = base;
2986 let Inst{4-0} = dst1;
2987
2988 let Constraints = "@earlyclobber $Ws";
2989}
2990
2991//---
2992// Exception generation
2993//---
2994
2995let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2996class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
2997 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
2998 Sched<[WriteSys]> {
2999 bits<16> imm;
3000 let Inst{31-24} = 0b11010100;
3001 let Inst{23-21} = op1;
3002 let Inst{20-5} = imm;
3003 let Inst{4-2} = 0b000;
3004 let Inst{1-0} = ll;
3005}
3006
3007//---
3008// Floating point to integer conversion
3009//---
3010
3011class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3012 RegisterClass srcType, RegisterClass dstType,
3013 string asm, list<dag> pattern>
3014 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3015 asm, "\t$Rd, $Rn", "", pattern>,
3016 Sched<[WriteFCvt]> {
3017 bits<5> Rd;
3018 bits<5> Rn;
3019 let Inst{30} = 0;
3020 let Inst{28-24} = 0b11110;
3021 let Inst{23-22} = type;
3022 let Inst{21} = 1;
3023 let Inst{20-19} = rmode;
3024 let Inst{18-16} = opcode;
3025 let Inst{15-10} = 0;
3026 let Inst{9-5} = Rn;
3027 let Inst{4-0} = Rd;
3028}
3029
3030let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3031class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3032 RegisterClass srcType, RegisterClass dstType,
3033 Operand immType, string asm>
3034 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3035 asm, "\t$Rd, $Rn, $scale", "", []>,
3036 Sched<[WriteFCvt]> {
3037 bits<5> Rd;
3038 bits<5> Rn;
3039 bits<6> scale;
3040 let Inst{30} = 0;
3041 let Inst{28-24} = 0b11110;
3042 let Inst{23-22} = type;
3043 let Inst{21} = 0;
3044 let Inst{20-19} = rmode;
3045 let Inst{18-16} = opcode;
3046 let Inst{15-10} = scale;
3047 let Inst{9-5} = Rn;
3048 let Inst{4-0} = Rd;
3049}
3050
3051multiclass FPToInteger<bits<2> rmode, bits<3> opcode, string asm, SDPatternOperator OpN> {
3052 // Unscaled single-precision to 32-bit
3053 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3054 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3055 let Inst{31} = 0; // 32-bit GPR flag
3056 }
3057
3058 // Unscaled single-precision to 64-bit
3059 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3060 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3061 let Inst{31} = 1; // 64-bit GPR flag
3062 }
3063
3064 // Unscaled double-precision to 32-bit
3065 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3066 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3067 let Inst{31} = 0; // 32-bit GPR flag
3068 }
3069
3070 // Unscaled double-precision to 64-bit
3071 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3072 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3073 let Inst{31} = 1; // 64-bit GPR flag
3074 }
3075
3076 // Scaled single-precision to 32-bit
3077 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3078 fixedpoint32, asm> {
3079 let Inst{31} = 0; // 32-bit GPR flag
3080 }
3081
3082 // Scaled single-precision to 64-bit
3083 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3084 fixedpoint64, asm> {
3085 let Inst{31} = 1; // 64-bit GPR flag
3086 }
3087
3088 // Scaled double-precision to 32-bit
3089 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3090 fixedpoint32, asm> {
3091 let Inst{31} = 0; // 32-bit GPR flag
3092 }
3093
3094 // Scaled double-precision to 64-bit
3095 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3096 fixedpoint64, asm> {
3097 let Inst{31} = 1; // 64-bit GPR flag
3098 }
3099}
3100
3101//---
3102// Integer to floating point conversion
3103//---
3104
3105let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3106class BaseIntegerToFP<bit isUnsigned,
3107 RegisterClass srcType, RegisterClass dstType,
3108 Operand immType, string asm>
3109 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3110 asm, "\t$Rd, $Rn, $scale", "", []>,
3111 Sched<[WriteFCvt]> {
3112 bits<5> Rd;
3113 bits<5> Rn;
3114 bits<6> scale;
3115 let Inst{30-23} = 0b00111100;
3116 let Inst{21-17} = 0b00001;
3117 let Inst{16} = isUnsigned;
3118 let Inst{15-10} = scale;
3119 let Inst{9-5} = Rn;
3120 let Inst{4-0} = Rd;
3121}
3122
3123class BaseIntegerToFPUnscaled<bit isUnsigned,
3124 RegisterClass srcType, RegisterClass dstType,
3125 ValueType dvt, string asm, SDNode node>
3126 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3127 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3128 Sched<[WriteFCvt]> {
3129 bits<5> Rd;
3130 bits<5> Rn;
3131 bits<6> scale;
3132 let Inst{30-23} = 0b00111100;
3133 let Inst{21-17} = 0b10001;
3134 let Inst{16} = isUnsigned;
3135 let Inst{15-10} = 0b000000;
3136 let Inst{9-5} = Rn;
3137 let Inst{4-0} = Rd;
3138}
3139
3140multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3141 // Unscaled
3142 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3143 let Inst{31} = 0; // 32-bit GPR flag
3144 let Inst{22} = 0; // 32-bit FPR flag
3145 }
3146
3147 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3148 let Inst{31} = 0; // 32-bit GPR flag
3149 let Inst{22} = 1; // 64-bit FPR flag
3150 }
3151
3152 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3153 let Inst{31} = 1; // 64-bit GPR flag
3154 let Inst{22} = 0; // 32-bit FPR flag
3155 }
3156
3157 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3158 let Inst{31} = 1; // 64-bit GPR flag
3159 let Inst{22} = 1; // 64-bit FPR flag
3160 }
3161
3162 // Scaled
3163 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint32, asm> {
3164 let Inst{31} = 0; // 32-bit GPR flag
3165 let Inst{22} = 0; // 32-bit FPR flag
3166 }
3167
3168 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint32, asm> {
3169 let Inst{31} = 0; // 32-bit GPR flag
3170 let Inst{22} = 1; // 64-bit FPR flag
3171 }
3172
3173 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint64, asm> {
3174 let Inst{31} = 1; // 64-bit GPR flag
3175 let Inst{22} = 0; // 32-bit FPR flag
3176 }
3177
3178 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint64, asm> {
3179 let Inst{31} = 1; // 64-bit GPR flag
3180 let Inst{22} = 1; // 64-bit FPR flag
3181 }
3182}
3183
3184//---
3185// Unscaled integer <-> floating point conversion (i.e. FMOV)
3186//---
3187
3188let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3189class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3190 RegisterClass srcType, RegisterClass dstType,
3191 string asm>
3192 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3193 // We use COPY_TO_REGCLASS for these bitconvert operations.
3194 // copyPhysReg() expands the resultant COPY instructions after
3195 // regalloc is done. This gives greater freedom for the allocator
3196 // and related passes (coalescing, copy propagation, et. al.) to
3197 // be more effective.
3198 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3199 Sched<[WriteFCopy]> {
3200 bits<5> Rd;
3201 bits<5> Rn;
3202 let Inst{30-23} = 0b00111100;
3203 let Inst{21} = 1;
3204 let Inst{20-19} = rmode;
3205 let Inst{18-16} = opcode;
3206 let Inst{15-10} = 0b000000;
3207 let Inst{9-5} = Rn;
3208 let Inst{4-0} = Rd;
3209}
3210
3211let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3212class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3213 RegisterClass srcType, RegisterOperand dstType, string asm>
3214 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd[1], $Rn", "", []>,
3215 Sched<[WriteFCopy]> {
3216 bits<5> Rd;
3217 bits<5> Rn;
3218 let Inst{30-23} = 0b00111101;
3219 let Inst{21} = 1;
3220 let Inst{20-19} = rmode;
3221 let Inst{18-16} = opcode;
3222 let Inst{15-10} = 0b000000;
3223 let Inst{9-5} = Rn;
3224 let Inst{4-0} = Rd;
3225}
3226
3227let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3228class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3229 RegisterOperand srcType, RegisterClass dstType, string asm>
3230 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn[1]", "", []>,
3231 Sched<[WriteFCopy]> {
3232 bits<5> Rd;
3233 bits<5> Rn;
3234 let Inst{30-23} = 0b00111101;
3235 let Inst{21} = 1;
3236 let Inst{20-19} = rmode;
3237 let Inst{18-16} = opcode;
3238 let Inst{15-10} = 0b000000;
3239 let Inst{9-5} = Rn;
3240 let Inst{4-0} = Rd;
3241}
3242
3243
3244
3245multiclass UnscaledConversion<string asm> {
3246 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3247 let Inst{31} = 0; // 32-bit GPR flag
3248 let Inst{22} = 0; // 32-bit FPR flag
3249 }
3250
3251 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3252 let Inst{31} = 1; // 64-bit GPR flag
3253 let Inst{22} = 1; // 64-bit FPR flag
3254 }
3255
3256 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3257 let Inst{31} = 0; // 32-bit GPR flag
3258 let Inst{22} = 0; // 32-bit FPR flag
3259 }
3260
3261 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3262 let Inst{31} = 1; // 64-bit GPR flag
3263 let Inst{22} = 1; // 64-bit FPR flag
3264 }
3265
3266 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3267 asm#".d"> {
3268 let Inst{31} = 1;
3269 let Inst{22} = 0;
3270 }
3271
3272 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3273 asm#".d"> {
3274 let Inst{31} = 1;
3275 let Inst{22} = 0;
3276 }
3277
3278 def : InstAlias<asm#"$Vd.d[1], $Rn",
3279 (!cast<Instruction>(NAME#XDHighr) V128:$Vd, GPR64:$Rn), 0>;
3280 def : InstAlias<asm#"$Rd, $Vn.d[1]",
3281 (!cast<Instruction>(NAME#DXHighr) GPR64:$Rd, V128:$Vn), 0>;
3282}
3283
3284//---
3285// Floating point conversion
3286//---
3287
3288class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3289 RegisterClass srcType, string asm, list<dag> pattern>
3290 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3291 Sched<[WriteFCvt]> {
3292 bits<5> Rd;
3293 bits<5> Rn;
3294 let Inst{31-24} = 0b00011110;
3295 let Inst{23-22} = type;
3296 let Inst{21-17} = 0b10001;
3297 let Inst{16-15} = opcode;
3298 let Inst{14-10} = 0b10000;
3299 let Inst{9-5} = Rn;
3300 let Inst{4-0} = Rd;
3301}
3302
3303multiclass FPConversion<string asm> {
3304 // Double-precision to Half-precision
3305 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3306 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, []>;
3307
3308 // Double-precision to Single-precision
3309 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3310 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3311
3312 // Half-precision to Double-precision
3313 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3314 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, []>;
3315
3316 // Half-precision to Single-precision
3317 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3318 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, []>;
3319
3320 // Single-precision to Double-precision
3321 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3322 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3323
3324 // Single-precision to Half-precision
3325 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3326 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, []>;
3327}
3328
3329//---
3330// Single operand floating point data processing
3331//---
3332
3333let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3334class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3335 ValueType vt, string asm, SDPatternOperator node>
3336 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3337 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3338 Sched<[WriteF]> {
3339 bits<5> Rd;
3340 bits<5> Rn;
3341 let Inst{31-23} = 0b000111100;
3342 let Inst{21-19} = 0b100;
3343 let Inst{18-15} = opcode;
3344 let Inst{14-10} = 0b10000;
3345 let Inst{9-5} = Rn;
3346 let Inst{4-0} = Rd;
3347}
3348
3349multiclass SingleOperandFPData<bits<4> opcode, string asm,
3350 SDPatternOperator node = null_frag> {
3351 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3352 let Inst{22} = 0; // 32-bit size flag
3353 }
3354
3355 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3356 let Inst{22} = 1; // 64-bit size flag
3357 }
3358}
3359
3360//---
3361// Two operand floating point data processing
3362//---
3363
3364let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3365class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3366 string asm, list<dag> pat>
3367 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3368 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3369 Sched<[WriteF]> {
3370 bits<5> Rd;
3371 bits<5> Rn;
3372 bits<5> Rm;
3373 let Inst{31-23} = 0b000111100;
3374 let Inst{21} = 1;
3375 let Inst{20-16} = Rm;
3376 let Inst{15-12} = opcode;
3377 let Inst{11-10} = 0b10;
3378 let Inst{9-5} = Rn;
3379 let Inst{4-0} = Rd;
3380}
3381
3382multiclass TwoOperandFPData<bits<4> opcode, string asm,
3383 SDPatternOperator node = null_frag> {
3384 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3385 [(set (f32 FPR32:$Rd),
3386 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3387 let Inst{22} = 0; // 32-bit size flag
3388 }
3389
3390 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3391 [(set (f64 FPR64:$Rd),
3392 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3393 let Inst{22} = 1; // 64-bit size flag
3394 }
3395}
3396
3397multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3398 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3399 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3400 let Inst{22} = 0; // 32-bit size flag
3401 }
3402
3403 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3404 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3405 let Inst{22} = 1; // 64-bit size flag
3406 }
3407}
3408
3409
3410//---
3411// Three operand floating point data processing
3412//---
3413
3414class BaseThreeOperandFPData<bit isNegated, bit isSub,
3415 RegisterClass regtype, string asm, list<dag> pat>
3416 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3417 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3418 Sched<[WriteFMul]> {
3419 bits<5> Rd;
3420 bits<5> Rn;
3421 bits<5> Rm;
3422 bits<5> Ra;
3423 let Inst{31-23} = 0b000111110;
3424 let Inst{21} = isNegated;
3425 let Inst{20-16} = Rm;
3426 let Inst{15} = isSub;
3427 let Inst{14-10} = Ra;
3428 let Inst{9-5} = Rn;
3429 let Inst{4-0} = Rd;
3430}
3431
3432multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3433 SDPatternOperator node> {
3434 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3435 [(set FPR32:$Rd,
3436 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3437 let Inst{22} = 0; // 32-bit size flag
3438 }
3439
3440 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3441 [(set FPR64:$Rd,
3442 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3443 let Inst{22} = 1; // 64-bit size flag
3444 }
3445}
3446
3447//---
3448// Floating point data comparisons
3449//---
3450
3451let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3452class BaseOneOperandFPComparison<bit signalAllNans,
3453 RegisterClass regtype, string asm,
3454 list<dag> pat>
3455 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3456 Sched<[WriteFCmp]> {
3457 bits<5> Rn;
3458 let Inst{31-23} = 0b000111100;
3459 let Inst{21} = 1;
3460
3461 let Inst{20-16} = 0b00000;
3462 let Inst{15-10} = 0b001000;
3463 let Inst{9-5} = Rn;
3464 let Inst{4} = signalAllNans;
3465 let Inst{3-0} = 0b1000;
3466}
3467
3468let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3469class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3470 string asm, list<dag> pat>
3471 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3472 Sched<[WriteFCmp]> {
3473 bits<5> Rm;
3474 bits<5> Rn;
3475 let Inst{31-23} = 0b000111100;
3476 let Inst{21} = 1;
3477 let Inst{20-16} = Rm;
3478 let Inst{15-10} = 0b001000;
3479 let Inst{9-5} = Rn;
3480 let Inst{4} = signalAllNans;
3481 let Inst{3-0} = 0b0000;
3482}
3483
3484multiclass FPComparison<bit signalAllNans, string asm,
3485 SDPatternOperator OpNode = null_frag> {
3486 let Defs = [CPSR] in {
3487 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3488 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3489 let Inst{22} = 0;
3490 }
3491
3492 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3493 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3494 let Inst{22} = 0;
3495 }
3496
3497 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3498 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3499 let Inst{22} = 1;
3500 }
3501
3502 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3503 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3504 let Inst{22} = 1;
3505 }
3506 } // Defs = [CPSR]
3507}
3508
3509//---
3510// Floating point conditional comparisons
3511//---
3512
3513let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3514class BaseFPCondComparison<bit signalAllNans,
3515 RegisterClass regtype, string asm>
3516 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3517 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3518 Sched<[WriteFCmp]> {
3519 bits<5> Rn;
3520 bits<5> Rm;
3521 bits<4> nzcv;
3522 bits<4> cond;
3523
3524 let Inst{31-23} = 0b000111100;
3525 let Inst{21} = 1;
3526 let Inst{20-16} = Rm;
3527 let Inst{15-12} = cond;
3528 let Inst{11-10} = 0b01;
3529 let Inst{9-5} = Rn;
3530 let Inst{4} = signalAllNans;
3531 let Inst{3-0} = nzcv;
3532}
3533
3534multiclass FPCondComparison<bit signalAllNans, string asm> {
3535 let Defs = [CPSR], Uses = [CPSR] in {
3536 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3537 let Inst{22} = 0;
3538 }
3539
3540 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3541 let Inst{22} = 1;
3542 }
3543 } // Defs = [CPSR], Uses = [CPSR]
3544}
3545
3546//---
3547// Floating point conditional select
3548//---
3549
3550class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3551 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3552 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3553 [(set regtype:$Rd,
3554 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3555 (i32 imm:$cond), CPSR))]>,
3556 Sched<[WriteF]> {
3557 bits<5> Rd;
3558 bits<5> Rn;
3559 bits<5> Rm;
3560 bits<4> cond;
3561
3562 let Inst{31-23} = 0b000111100;
3563 let Inst{21} = 1;
3564 let Inst{20-16} = Rm;
3565 let Inst{15-12} = cond;
3566 let Inst{11-10} = 0b11;
3567 let Inst{9-5} = Rn;
3568 let Inst{4-0} = Rd;
3569}
3570
3571multiclass FPCondSelect<string asm> {
3572 let Uses = [CPSR] in {
3573 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3574 let Inst{22} = 0;
3575 }
3576
3577 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3578 let Inst{22} = 1;
3579 }
3580 } // Uses = [CPSR]
3581}
3582
3583//---
3584// Floating move immediate
3585//---
3586
3587class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3588 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3589 [(set regtype:$Rd, fpimmtype:$imm)]>,
3590 Sched<[WriteFImm]> {
3591 bits<5> Rd;
3592 bits<8> imm;
3593 let Inst{31-23} = 0b000111100;
3594 let Inst{21} = 1;
3595 let Inst{20-13} = imm;
3596 let Inst{12-5} = 0b10000000;
3597 let Inst{4-0} = Rd;
3598}
3599
3600multiclass FPMoveImmediate<string asm> {
3601 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3602 let Inst{22} = 0;
3603 }
3604
3605 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3606 let Inst{22} = 1;
3607 }
3608}
3609
3610//----------------------------------------------------------------------------
3611// AdvSIMD
3612//----------------------------------------------------------------------------
3613
3614def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3615def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3616def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3617def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3618def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3619 return ((uint64_t)Imm) < 16;
3620}]> {
3621 let ParserMatchClass = VectorIndexBOperand;
3622 let PrintMethod = "printVectorIndex";
3623 let MIOperandInfo = (ops i64imm);
3624}
3625def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3626 return ((uint64_t)Imm) < 8;
3627}]> {
3628 let ParserMatchClass = VectorIndexHOperand;
3629 let PrintMethod = "printVectorIndex";
3630 let MIOperandInfo = (ops i64imm);
3631}
3632def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3633 return ((uint64_t)Imm) < 4;
3634}]> {
3635 let ParserMatchClass = VectorIndexSOperand;
3636 let PrintMethod = "printVectorIndex";
3637 let MIOperandInfo = (ops i64imm);
3638}
3639def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3640 return ((uint64_t)Imm) < 2;
3641}]> {
3642 let ParserMatchClass = VectorIndexDOperand;
3643 let PrintMethod = "printVectorIndex";
3644 let MIOperandInfo = (ops i64imm);
3645}
3646
3647//----------------------------------------------------------------------------
3648// AdvSIMD three register vector instructions
3649//----------------------------------------------------------------------------
3650
3651let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3652class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3653 RegisterOperand regtype, string asm, string kind,
3654 list<dag> pattern>
3655 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3656 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3657 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3658 Sched<[WriteV]> {
3659 bits<5> Rd;
3660 bits<5> Rn;
3661 bits<5> Rm;
3662 let Inst{31} = 0;
3663 let Inst{30} = Q;
3664 let Inst{29} = U;
3665 let Inst{28-24} = 0b01110;
3666 let Inst{23-22} = size;
3667 let Inst{21} = 1;
3668 let Inst{20-16} = Rm;
3669 let Inst{15-11} = opcode;
3670 let Inst{10} = 1;
3671 let Inst{9-5} = Rn;
3672 let Inst{4-0} = Rd;
3673}
3674
3675let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3676class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3677 RegisterOperand regtype, string asm, string kind,
3678 list<dag> pattern>
3679 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3680 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3681 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3682 Sched<[WriteV]> {
3683 bits<5> Rd;
3684 bits<5> Rn;
3685 bits<5> Rm;
3686 let Inst{31} = 0;
3687 let Inst{30} = Q;
3688 let Inst{29} = U;
3689 let Inst{28-24} = 0b01110;
3690 let Inst{23-22} = size;
3691 let Inst{21} = 1;
3692 let Inst{20-16} = Rm;
3693 let Inst{15-11} = opcode;
3694 let Inst{10} = 1;
3695 let Inst{9-5} = Rn;
3696 let Inst{4-0} = Rd;
3697}
3698
3699// All operand sizes distinguished in the encoding.
3700multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3701 SDPatternOperator OpNode> {
3702 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3703 asm, ".8b",
3704 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3705 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3706 asm, ".16b",
3707 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3708 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3709 asm, ".4h",
3710 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3711 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3712 asm, ".8h",
3713 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3714 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3715 asm, ".2s",
3716 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3717 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3718 asm, ".4s",
3719 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3720 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3721 asm, ".2d",
3722 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3723}
3724
3725// As above, but D sized elements unsupported.
3726multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3727 SDPatternOperator OpNode> {
3728 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3729 asm, ".8b",
3730 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3731 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3732 asm, ".16b",
3733 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3734 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3735 asm, ".4h",
3736 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3737 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3738 asm, ".8h",
3739 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3740 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3741 asm, ".2s",
3742 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3743 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3744 asm, ".4s",
3745 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3746}
3747
3748multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3749 SDPatternOperator OpNode> {
3750 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3751 asm, ".8b",
3752 [(set (v8i8 V64:$dst),
3753 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3754 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3755 asm, ".16b",
3756 [(set (v16i8 V128:$dst),
3757 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3758 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3759 asm, ".4h",
3760 [(set (v4i16 V64:$dst),
3761 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3762 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3763 asm, ".8h",
3764 [(set (v8i16 V128:$dst),
3765 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3766 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3767 asm, ".2s",
3768 [(set (v2i32 V64:$dst),
3769 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3770 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3771 asm, ".4s",
3772 [(set (v4i32 V128:$dst),
3773 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3774}
3775
3776// As above, but only B sized elements supported.
3777multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3778 SDPatternOperator OpNode> {
3779 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3780 asm, ".8b",
3781 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3782 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3783 asm, ".16b",
3784 [(set (v16i8 V128:$Rd),
3785 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3786}
3787
3788// As above, but only S and D sized floating point elements supported.
3789multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3790 string asm, SDPatternOperator OpNode> {
3791 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3792 asm, ".2s",
3793 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3794 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3795 asm, ".4s",
3796 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3797 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3798 asm, ".2d",
3799 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3800}
3801
3802multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3803 string asm,
3804 SDPatternOperator OpNode> {
3805 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3806 asm, ".2s",
3807 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3808 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3809 asm, ".4s",
3810 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3811 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3812 asm, ".2d",
3813 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3814}
3815
3816multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3817 string asm, SDPatternOperator OpNode> {
3818 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3819 asm, ".2s",
3820 [(set (v2f32 V64:$dst),
3821 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3822 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3823 asm, ".4s",
3824 [(set (v4f32 V128:$dst),
3825 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3826 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3827 asm, ".2d",
3828 [(set (v2f64 V128:$dst),
3829 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3830}
3831
3832// As above, but D and B sized elements unsupported.
3833multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3834 SDPatternOperator OpNode> {
3835 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3836 asm, ".4h",
3837 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3838 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3839 asm, ".8h",
3840 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3841 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3842 asm, ".2s",
3843 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3844 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3845 asm, ".4s",
3846 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3847}
3848
3849// Logical three vector ops share opcode bits, and only use B sized elements.
3850multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3851 SDPatternOperator OpNode = null_frag> {
3852 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3853 asm, ".8b",
3854 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3855 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3856 asm, ".16b",
3857 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3858
3859 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3860 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3861 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3862 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3863 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3864 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3865
3866 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3867 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3868 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3869 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3870 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3871 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3872}
3873
3874multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3875 string asm, SDPatternOperator OpNode> {
3876 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3877 asm, ".8b",
3878 [(set (v8i8 V64:$dst),
3879 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3880 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3881 asm, ".16b",
3882 [(set (v16i8 V128:$dst),
3883 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3884 (v16i8 V128:$Rm)))]>;
3885
3886 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3887 (v4i16 V64:$RHS))),
3888 (!cast<Instruction>(NAME#"v8i8")
3889 V64:$LHS, V64:$MHS, V64:$RHS)>;
3890 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3891 (v2i32 V64:$RHS))),
3892 (!cast<Instruction>(NAME#"v8i8")
3893 V64:$LHS, V64:$MHS, V64:$RHS)>;
3894 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3895 (v1i64 V64:$RHS))),
3896 (!cast<Instruction>(NAME#"v8i8")
3897 V64:$LHS, V64:$MHS, V64:$RHS)>;
3898
3899 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3900 (v8i16 V128:$RHS))),
3901 (!cast<Instruction>(NAME#"v16i8")
3902 V128:$LHS, V128:$MHS, V128:$RHS)>;
3903 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
3904 (v4i32 V128:$RHS))),
3905 (!cast<Instruction>(NAME#"v16i8")
3906 V128:$LHS, V128:$MHS, V128:$RHS)>;
3907 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
3908 (v2i64 V128:$RHS))),
3909 (!cast<Instruction>(NAME#"v16i8")
3910 V128:$LHS, V128:$MHS, V128:$RHS)>;
3911}
3912
3913
3914//----------------------------------------------------------------------------
3915// AdvSIMD two register vector instructions.
3916//----------------------------------------------------------------------------
3917
3918let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3919class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3920 RegisterOperand regtype, string asm, string dstkind,
3921 string srckind, list<dag> pattern>
3922 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
3923 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3924 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
3925 Sched<[WriteV]> {
3926 bits<5> Rd;
3927 bits<5> Rn;
3928 let Inst{31} = 0;
3929 let Inst{30} = Q;
3930 let Inst{29} = U;
3931 let Inst{28-24} = 0b01110;
3932 let Inst{23-22} = size;
3933 let Inst{21-17} = 0b10000;
3934 let Inst{16-12} = opcode;
3935 let Inst{11-10} = 0b10;
3936 let Inst{9-5} = Rn;
3937 let Inst{4-0} = Rd;
3938}
3939
3940let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3941class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3942 RegisterOperand regtype, string asm, string dstkind,
3943 string srckind, list<dag> pattern>
3944 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
3945 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3946 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
3947 Sched<[WriteV]> {
3948 bits<5> Rd;
3949 bits<5> Rn;
3950 let Inst{31} = 0;
3951 let Inst{30} = Q;
3952 let Inst{29} = U;
3953 let Inst{28-24} = 0b01110;
3954 let Inst{23-22} = size;
3955 let Inst{21-17} = 0b10000;
3956 let Inst{16-12} = opcode;
3957 let Inst{11-10} = 0b10;
3958 let Inst{9-5} = Rn;
3959 let Inst{4-0} = Rd;
3960}
3961
3962// Supports B, H, and S element sizes.
3963multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
3964 SDPatternOperator OpNode> {
3965 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
3966 asm, ".8b", ".8b",
3967 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
3968 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
3969 asm, ".16b", ".16b",
3970 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
3971 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
3972 asm, ".4h", ".4h",
3973 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
3974 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
3975 asm, ".8h", ".8h",
3976 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
3977 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
3978 asm, ".2s", ".2s",
3979 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
3980 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
3981 asm, ".4s", ".4s",
3982 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
3983}
3984
3985class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
3986 RegisterOperand regtype, string asm, string dstkind,
3987 string srckind, string amount>
3988 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
3989 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
3990 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
3991 Sched<[WriteV]> {
3992 bits<5> Rd;
3993 bits<5> Rn;
3994 let Inst{31} = 0;
3995 let Inst{30} = Q;
3996 let Inst{29-24} = 0b101110;
3997 let Inst{23-22} = size;
3998 let Inst{21-10} = 0b100001001110;
3999 let Inst{9-5} = Rn;
4000 let Inst{4-0} = Rd;
4001}
4002
4003multiclass SIMDVectorLShiftLongBySizeBHS {
4004 let neverHasSideEffects = 1 in {
4005 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4006 "shll", ".8h", ".8b", "8">;
4007 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4008 "shll2", ".8h", ".16b", "8">;
4009 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4010 "shll", ".4s", ".4h", "16">;
4011 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4012 "shll2", ".4s", ".8h", "16">;
4013 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4014 "shll", ".2d", ".2s", "32">;
4015 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4016 "shll2", ".2d", ".4s", "32">;
4017 }
4018}
4019
4020// Supports all element sizes.
4021multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4022 SDPatternOperator OpNode> {
4023 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4024 asm, ".4h", ".8b",
4025 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4026 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4027 asm, ".8h", ".16b",
4028 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4029 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4030 asm, ".2s", ".4h",
4031 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4032 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4033 asm, ".4s", ".8h",
4034 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4035 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4036 asm, ".1d", ".2s",
4037 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4038 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4039 asm, ".2d", ".4s",
4040 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4041}
4042
4043multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4044 SDPatternOperator OpNode> {
4045 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4046 asm, ".4h", ".8b",
4047 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4048 (v8i8 V64:$Rn)))]>;
4049 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4050 asm, ".8h", ".16b",
4051 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4052 (v16i8 V128:$Rn)))]>;
4053 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4054 asm, ".2s", ".4h",
4055 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4056 (v4i16 V64:$Rn)))]>;
4057 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4058 asm, ".4s", ".8h",
4059 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4060 (v8i16 V128:$Rn)))]>;
4061 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4062 asm, ".1d", ".2s",
4063 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4064 (v2i32 V64:$Rn)))]>;
4065 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4066 asm, ".2d", ".4s",
4067 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4068 (v4i32 V128:$Rn)))]>;
4069}
4070
4071// Supports all element sizes, except 1xD.
4072multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4073 SDPatternOperator OpNode> {
4074 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4075 asm, ".8b", ".8b",
4076 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4077 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4078 asm, ".16b", ".16b",
4079 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4080 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4081 asm, ".4h", ".4h",
4082 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4083 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4084 asm, ".8h", ".8h",
4085 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4086 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4087 asm, ".2s", ".2s",
4088 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4089 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4090 asm, ".4s", ".4s",
4091 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4092 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4093 asm, ".2d", ".2d",
4094 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4095}
4096
4097multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4098 SDPatternOperator OpNode = null_frag> {
4099 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4100 asm, ".8b", ".8b",
4101 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4102 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4103 asm, ".16b", ".16b",
4104 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4105 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4106 asm, ".4h", ".4h",
4107 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4108 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4109 asm, ".8h", ".8h",
4110 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4111 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4112 asm, ".2s", ".2s",
4113 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4114 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4115 asm, ".4s", ".4s",
4116 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4117 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4118 asm, ".2d", ".2d",
4119 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4120}
4121
4122
4123// Supports only B element sizes.
4124multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4125 SDPatternOperator OpNode> {
4126 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4127 asm, ".8b", ".8b",
4128 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4129 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4130 asm, ".16b", ".16b",
4131 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4132
4133}
4134
4135// Supports only B and H element sizes.
4136multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4137 SDPatternOperator OpNode> {
4138 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4139 asm, ".8b", ".8b",
4140 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4141 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4142 asm, ".16b", ".16b",
4143 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4144 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4145 asm, ".4h", ".4h",
4146 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4147 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4148 asm, ".8h", ".8h",
4149 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4150}
4151
4152// Supports only S and D element sizes, uses high bit of the size field
4153// as an extra opcode bit.
4154multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4155 SDPatternOperator OpNode> {
4156 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4157 asm, ".2s", ".2s",
4158 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4159 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4160 asm, ".4s", ".4s",
4161 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4162 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4163 asm, ".2d", ".2d",
4164 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4165}
4166
4167// Supports only S element size.
4168multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4169 SDPatternOperator OpNode> {
4170 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4171 asm, ".2s", ".2s",
4172 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4173 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4174 asm, ".4s", ".4s",
4175 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4176}
4177
4178
4179multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4180 SDPatternOperator OpNode> {
4181 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4182 asm, ".2s", ".2s",
4183 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4184 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4185 asm, ".4s", ".4s",
4186 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4187 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4188 asm, ".2d", ".2d",
4189 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4190}
4191
4192multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4193 SDPatternOperator OpNode> {
4194 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4195 asm, ".2s", ".2s",
4196 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4197 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4198 asm, ".4s", ".4s",
4199 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4200 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4201 asm, ".2d", ".2d",
4202 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4203}
4204
4205
4206class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4207 RegisterOperand inreg, RegisterOperand outreg,
4208 string asm, string outkind, string inkind,
4209 list<dag> pattern>
4210 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4211 "{\t$Rd" # outkind # ", $Rn" # inkind #
4212 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4213 Sched<[WriteV]> {
4214 bits<5> Rd;
4215 bits<5> Rn;
4216 let Inst{31} = 0;
4217 let Inst{30} = Q;
4218 let Inst{29} = U;
4219 let Inst{28-24} = 0b01110;
4220 let Inst{23-22} = size;
4221 let Inst{21-17} = 0b10000;
4222 let Inst{16-12} = opcode;
4223 let Inst{11-10} = 0b10;
4224 let Inst{9-5} = Rn;
4225 let Inst{4-0} = Rd;
4226}
4227
4228class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4229 RegisterOperand inreg, RegisterOperand outreg,
4230 string asm, string outkind, string inkind,
4231 list<dag> pattern>
4232 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4233 "{\t$Rd" # outkind # ", $Rn" # inkind #
4234 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4235 Sched<[WriteV]> {
4236 bits<5> Rd;
4237 bits<5> Rn;
4238 let Inst{31} = 0;
4239 let Inst{30} = Q;
4240 let Inst{29} = U;
4241 let Inst{28-24} = 0b01110;
4242 let Inst{23-22} = size;
4243 let Inst{21-17} = 0b10000;
4244 let Inst{16-12} = opcode;
4245 let Inst{11-10} = 0b10;
4246 let Inst{9-5} = Rn;
4247 let Inst{4-0} = Rd;
4248}
4249
4250multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4251 SDPatternOperator OpNode> {
4252 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4253 asm, ".8b", ".8h",
4254 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4255 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4256 asm#"2", ".16b", ".8h", []>;
4257 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4258 asm, ".4h", ".4s",
4259 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4260 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4261 asm#"2", ".8h", ".4s", []>;
4262 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4263 asm, ".2s", ".2d",
4264 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4265 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4266 asm#"2", ".4s", ".2d", []>;
4267
4268 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4269 (!cast<Instruction>(NAME # "v16i8")
4270 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4271 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4272 (!cast<Instruction>(NAME # "v8i16")
4273 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4274 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4275 (!cast<Instruction>(NAME # "v4i32")
4276 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4277}
4278
4279class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4280 RegisterOperand regtype, string asm, string kind,
4281 ValueType dty, ValueType sty, SDNode OpNode>
4282 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4283 "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4284 "|" # kind # "\t$Rd, $Rn, #0}", "",
4285 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4286 Sched<[WriteV]> {
4287 bits<5> Rd;
4288 bits<5> Rn;
4289 let Inst{31} = 0;
4290 let Inst{30} = Q;
4291 let Inst{29} = U;
4292 let Inst{28-24} = 0b01110;
4293 let Inst{23-22} = size;
4294 let Inst{21-17} = 0b10000;
4295 let Inst{16-12} = opcode;
4296 let Inst{11-10} = 0b10;
4297 let Inst{9-5} = Rn;
4298 let Inst{4-0} = Rd;
4299}
4300
4301// Comparisons support all element sizes, except 1xD.
4302multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4303 SDNode OpNode> {
4304 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4305 asm, ".8b",
4306 v8i8, v8i8, OpNode>;
4307 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4308 asm, ".16b",
4309 v16i8, v16i8, OpNode>;
4310 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4311 asm, ".4h",
4312 v4i16, v4i16, OpNode>;
4313 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4314 asm, ".8h",
4315 v8i16, v8i16, OpNode>;
4316 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4317 asm, ".2s",
4318 v2i32, v2i32, OpNode>;
4319 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4320 asm, ".4s",
4321 v4i32, v4i32, OpNode>;
4322 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4323 asm, ".2d",
4324 v2i64, v2i64, OpNode>;
4325}
4326
4327// FP Comparisons support only S and D element sizes.
4328multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4329 string asm, SDNode OpNode> {
4330 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4331 asm, ".2s",
4332 v2i32, v2f32, OpNode>;
4333 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4334 asm, ".4s",
4335 v4i32, v4f32, OpNode>;
4336 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4337 asm, ".2d",
4338 v2i64, v2f64, OpNode>;
4339}
4340
4341let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4342class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4343 RegisterOperand outtype, RegisterOperand intype,
4344 string asm, string VdTy, string VnTy,
4345 list<dag> pattern>
4346 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4347 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4348 Sched<[WriteV]> {
4349 bits<5> Rd;
4350 bits<5> Rn;
4351 let Inst{31} = 0;
4352 let Inst{30} = Q;
4353 let Inst{29} = U;
4354 let Inst{28-24} = 0b01110;
4355 let Inst{23-22} = size;
4356 let Inst{21-17} = 0b10000;
4357 let Inst{16-12} = opcode;
4358 let Inst{11-10} = 0b10;
4359 let Inst{9-5} = Rn;
4360 let Inst{4-0} = Rd;
4361}
4362
4363class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4364 RegisterOperand outtype, RegisterOperand intype,
4365 string asm, string VdTy, string VnTy,
4366 list<dag> pattern>
4367 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4368 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4369 Sched<[WriteV]> {
4370 bits<5> Rd;
4371 bits<5> Rn;
4372 let Inst{31} = 0;
4373 let Inst{30} = Q;
4374 let Inst{29} = U;
4375 let Inst{28-24} = 0b01110;
4376 let Inst{23-22} = size;
4377 let Inst{21-17} = 0b10000;
4378 let Inst{16-12} = opcode;
4379 let Inst{11-10} = 0b10;
4380 let Inst{9-5} = Rn;
4381 let Inst{4-0} = Rd;
4382}
4383
4384multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4385 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4386 asm, ".4s", ".4h", []>;
4387 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4388 asm#"2", ".4s", ".8h", []>;
4389 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4390 asm, ".2d", ".2s", []>;
4391 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4392 asm#"2", ".2d", ".4s", []>;
4393}
4394
4395multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4396 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4397 asm, ".4h", ".4s", []>;
4398 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4399 asm#"2", ".8h", ".4s", []>;
4400 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4401 asm, ".2s", ".2d", []>;
4402 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4403 asm#"2", ".4s", ".2d", []>;
4404}
4405
4406multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4407 Intrinsic OpNode> {
4408 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4409 asm, ".2s", ".2d",
4410 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4411 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4412 asm#"2", ".4s", ".2d", []>;
4413
4414 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4415 (!cast<Instruction>(NAME # "v4f32")
4416 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4417}
4418
4419//----------------------------------------------------------------------------
4420// AdvSIMD three register different-size vector instructions.
4421//----------------------------------------------------------------------------
4422
4423let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4424class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4425 RegisterOperand outtype, RegisterOperand intype1,
4426 RegisterOperand intype2, string asm,
4427 string outkind, string inkind1, string inkind2,
4428 list<dag> pattern>
4429 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4430 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4431 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4432 Sched<[WriteV]> {
4433 bits<5> Rd;
4434 bits<5> Rn;
4435 bits<5> Rm;
4436 let Inst{31} = 0;
4437 let Inst{30} = size{0};
4438 let Inst{29} = U;
4439 let Inst{28-24} = 0b01110;
4440 let Inst{23-22} = size{2-1};
4441 let Inst{21} = 1;
4442 let Inst{20-16} = Rm;
4443 let Inst{15-12} = opcode;
4444 let Inst{11-10} = 0b00;
4445 let Inst{9-5} = Rn;
4446 let Inst{4-0} = Rd;
4447}
4448
4449let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4450class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4451 RegisterOperand outtype, RegisterOperand intype1,
4452 RegisterOperand intype2, string asm,
4453 string outkind, string inkind1, string inkind2,
4454 list<dag> pattern>
4455 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4456 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4457 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4458 Sched<[WriteV]> {
4459 bits<5> Rd;
4460 bits<5> Rn;
4461 bits<5> Rm;
4462 let Inst{31} = 0;
4463 let Inst{30} = size{0};
4464 let Inst{29} = U;
4465 let Inst{28-24} = 0b01110;
4466 let Inst{23-22} = size{2-1};
4467 let Inst{21} = 1;
4468 let Inst{20-16} = Rm;
4469 let Inst{15-12} = opcode;
4470 let Inst{11-10} = 0b00;
4471 let Inst{9-5} = Rn;
4472 let Inst{4-0} = Rd;
4473}
4474
4475// FIXME: TableGen doesn't know how to deal with expanded types that also
4476// change the element count (in this case, placing the results in
4477// the high elements of the result register rather than the low
4478// elements). Until that's fixed, we can't code-gen those.
4479multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4480 Intrinsic IntOp> {
4481 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4482 V64, V128, V128,
4483 asm, ".8b", ".8h", ".8h",
4484 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4485 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4486 V128, V128, V128,
4487 asm#"2", ".16b", ".8h", ".8h",
4488 []>;
4489 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4490 V64, V128, V128,
4491 asm, ".4h", ".4s", ".4s",
4492 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4493 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4494 V128, V128, V128,
4495 asm#"2", ".8h", ".4s", ".4s",
4496 []>;
4497 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4498 V64, V128, V128,
4499 asm, ".2s", ".2d", ".2d",
4500 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4501 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4502 V128, V128, V128,
4503 asm#"2", ".4s", ".2d", ".2d",
4504 []>;
4505
4506
4507 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4508 // a version attached to an instruction.
4509 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4510 (v8i16 V128:$Rm))),
4511 (!cast<Instruction>(NAME # "v8i16_v16i8")
4512 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4513 V128:$Rn, V128:$Rm)>;
4514 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4515 (v4i32 V128:$Rm))),
4516 (!cast<Instruction>(NAME # "v4i32_v8i16")
4517 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4518 V128:$Rn, V128:$Rm)>;
4519 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4520 (v2i64 V128:$Rm))),
4521 (!cast<Instruction>(NAME # "v2i64_v4i32")
4522 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4523 V128:$Rn, V128:$Rm)>;
4524}
4525
4526multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4527 Intrinsic IntOp> {
4528 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4529 V128, V64, V64,
4530 asm, ".8h", ".8b", ".8b",
4531 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4532 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4533 V128, V128, V128,
4534 asm#"2", ".8h", ".16b", ".16b", []>;
4535 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4536 V128, V64, V64,
4537 asm, ".1q", ".1d", ".1d", []>;
4538 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4539 V128, V128, V128,
4540 asm#"2", ".1q", ".2d", ".2d", []>;
4541
4542 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4543 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4544 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4545}
4546
4547multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4548 SDPatternOperator OpNode> {
4549 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4550 V128, V64, V64,
4551 asm, ".4s", ".4h", ".4h",
4552 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4553 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4554 V128, V128, V128,
4555 asm#"2", ".4s", ".8h", ".8h",
4556 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4557 (extract_high_v8i16 V128:$Rm)))]>;
4558 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4559 V128, V64, V64,
4560 asm, ".2d", ".2s", ".2s",
4561 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4562 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4563 V128, V128, V128,
4564 asm#"2", ".2d", ".4s", ".4s",
4565 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4566 (extract_high_v4i32 V128:$Rm)))]>;
4567}
4568
4569multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4570 SDPatternOperator OpNode = null_frag> {
4571 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4572 V128, V64, V64,
4573 asm, ".8h", ".8b", ".8b",
4574 [(set (v8i16 V128:$Rd),
4575 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4576 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4577 V128, V128, V128,
4578 asm#"2", ".8h", ".16b", ".16b",
4579 [(set (v8i16 V128:$Rd),
4580 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4581 (extract_high_v16i8 V128:$Rm)))))]>;
4582 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4583 V128, V64, V64,
4584 asm, ".4s", ".4h", ".4h",
4585 [(set (v4i32 V128:$Rd),
4586 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4587 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4588 V128, V128, V128,
4589 asm#"2", ".4s", ".8h", ".8h",
4590 [(set (v4i32 V128:$Rd),
4591 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4592 (extract_high_v8i16 V128:$Rm)))))]>;
4593 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4594 V128, V64, V64,
4595 asm, ".2d", ".2s", ".2s",
4596 [(set (v2i64 V128:$Rd),
4597 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4598 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4599 V128, V128, V128,
4600 asm#"2", ".2d", ".4s", ".4s",
4601 [(set (v2i64 V128:$Rd),
4602 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4603 (extract_high_v4i32 V128:$Rm)))))]>;
4604}
4605
4606multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4607 string asm,
4608 SDPatternOperator OpNode> {
4609 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4610 V128, V64, V64,
4611 asm, ".8h", ".8b", ".8b",
4612 [(set (v8i16 V128:$dst),
4613 (add (v8i16 V128:$Rd),
4614 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4615 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4616 V128, V128, V128,
4617 asm#"2", ".8h", ".16b", ".16b",
4618 [(set (v8i16 V128:$dst),
4619 (add (v8i16 V128:$Rd),
4620 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4621 (extract_high_v16i8 V128:$Rm))))))]>;
4622 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4623 V128, V64, V64,
4624 asm, ".4s", ".4h", ".4h",
4625 [(set (v4i32 V128:$dst),
4626 (add (v4i32 V128:$Rd),
4627 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4628 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4629 V128, V128, V128,
4630 asm#"2", ".4s", ".8h", ".8h",
4631 [(set (v4i32 V128:$dst),
4632 (add (v4i32 V128:$Rd),
4633 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4634 (extract_high_v8i16 V128:$Rm))))))]>;
4635 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4636 V128, V64, V64,
4637 asm, ".2d", ".2s", ".2s",
4638 [(set (v2i64 V128:$dst),
4639 (add (v2i64 V128:$Rd),
4640 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4641 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4642 V128, V128, V128,
4643 asm#"2", ".2d", ".4s", ".4s",
4644 [(set (v2i64 V128:$dst),
4645 (add (v2i64 V128:$Rd),
4646 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4647 (extract_high_v4i32 V128:$Rm))))))]>;
4648}
4649
4650multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4651 SDPatternOperator OpNode = null_frag> {
4652 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4653 V128, V64, V64,
4654 asm, ".8h", ".8b", ".8b",
4655 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4656 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4657 V128, V128, V128,
4658 asm#"2", ".8h", ".16b", ".16b",
4659 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4660 (extract_high_v16i8 V128:$Rm)))]>;
4661 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4662 V128, V64, V64,
4663 asm, ".4s", ".4h", ".4h",
4664 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4665 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4666 V128, V128, V128,
4667 asm#"2", ".4s", ".8h", ".8h",
4668 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4669 (extract_high_v8i16 V128:$Rm)))]>;
4670 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4671 V128, V64, V64,
4672 asm, ".2d", ".2s", ".2s",
4673 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4674 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4675 V128, V128, V128,
4676 asm#"2", ".2d", ".4s", ".4s",
4677 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4678 (extract_high_v4i32 V128:$Rm)))]>;
4679}
4680
4681multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4682 string asm,
4683 SDPatternOperator OpNode> {
4684 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4685 V128, V64, V64,
4686 asm, ".8h", ".8b", ".8b",
4687 [(set (v8i16 V128:$dst),
4688 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4689 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4690 V128, V128, V128,
4691 asm#"2", ".8h", ".16b", ".16b",
4692 [(set (v8i16 V128:$dst),
4693 (OpNode (v8i16 V128:$Rd),
4694 (extract_high_v16i8 V128:$Rn),
4695 (extract_high_v16i8 V128:$Rm)))]>;
4696 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4697 V128, V64, V64,
4698 asm, ".4s", ".4h", ".4h",
4699 [(set (v4i32 V128:$dst),
4700 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4701 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4702 V128, V128, V128,
4703 asm#"2", ".4s", ".8h", ".8h",
4704 [(set (v4i32 V128:$dst),
4705 (OpNode (v4i32 V128:$Rd),
4706 (extract_high_v8i16 V128:$Rn),
4707 (extract_high_v8i16 V128:$Rm)))]>;
4708 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4709 V128, V64, V64,
4710 asm, ".2d", ".2s", ".2s",
4711 [(set (v2i64 V128:$dst),
4712 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4713 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4714 V128, V128, V128,
4715 asm#"2", ".2d", ".4s", ".4s",
4716 [(set (v2i64 V128:$dst),
4717 (OpNode (v2i64 V128:$Rd),
4718 (extract_high_v4i32 V128:$Rn),
4719 (extract_high_v4i32 V128:$Rm)))]>;
4720}
4721
4722multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4723 SDPatternOperator Accum> {
4724 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4725 V128, V64, V64,
4726 asm, ".4s", ".4h", ".4h",
4727 [(set (v4i32 V128:$dst),
4728 (Accum (v4i32 V128:$Rd),
4729 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4730 (v4i16 V64:$Rm)))))]>;
4731 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4732 V128, V128, V128,
4733 asm#"2", ".4s", ".8h", ".8h",
4734 [(set (v4i32 V128:$dst),
4735 (Accum (v4i32 V128:$Rd),
4736 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4737 (extract_high_v8i16 V128:$Rm)))))]>;
4738 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4739 V128, V64, V64,
4740 asm, ".2d", ".2s", ".2s",
4741 [(set (v2i64 V128:$dst),
4742 (Accum (v2i64 V128:$Rd),
4743 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4744 (v2i32 V64:$Rm)))))]>;
4745 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4746 V128, V128, V128,
4747 asm#"2", ".2d", ".4s", ".4s",
4748 [(set (v2i64 V128:$dst),
4749 (Accum (v2i64 V128:$Rd),
4750 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4751 (extract_high_v4i32 V128:$Rm)))))]>;
4752}
4753
4754multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4755 SDPatternOperator OpNode> {
4756 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4757 V128, V128, V64,
4758 asm, ".8h", ".8h", ".8b",
4759 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4760 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4761 V128, V128, V128,
4762 asm#"2", ".8h", ".8h", ".16b",
4763 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4764 (extract_high_v16i8 V128:$Rm)))]>;
4765 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4766 V128, V128, V64,
4767 asm, ".4s", ".4s", ".4h",
4768 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4769 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4770 V128, V128, V128,
4771 asm#"2", ".4s", ".4s", ".8h",
4772 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4773 (extract_high_v8i16 V128:$Rm)))]>;
4774 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4775 V128, V128, V64,
4776 asm, ".2d", ".2d", ".2s",
4777 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4778 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4779 V128, V128, V128,
4780 asm#"2", ".2d", ".2d", ".4s",
4781 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4782 (extract_high_v4i32 V128:$Rm)))]>;
4783}
4784
4785//----------------------------------------------------------------------------
4786// AdvSIMD bitwise extract from vector
4787//----------------------------------------------------------------------------
4788
4789class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4790 string asm, string kind>
4791 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4792 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4793 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4794 [(set (vty regtype:$Rd),
4795 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4796 Sched<[WriteV]> {
4797 bits<5> Rd;
4798 bits<5> Rn;
4799 bits<5> Rm;
4800 bits<4> imm;
4801 let Inst{31} = 0;
4802 let Inst{30} = size;
4803 let Inst{29-21} = 0b101110000;
4804 let Inst{20-16} = Rm;
4805 let Inst{15} = 0;
4806 let Inst{14-11} = imm;
4807 let Inst{10} = 0;
4808 let Inst{9-5} = Rn;
4809 let Inst{4-0} = Rd;
4810}
4811
4812
4813multiclass SIMDBitwiseExtract<string asm> {
4814 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b">;
4815 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4816}
4817
4818//----------------------------------------------------------------------------
4819// AdvSIMD zip vector
4820//----------------------------------------------------------------------------
4821
4822class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4823 string asm, string kind, SDNode OpNode, ValueType valty>
4824 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4825 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4826 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4827 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4828 Sched<[WriteV]> {
4829 bits<5> Rd;
4830 bits<5> Rn;
4831 bits<5> Rm;
4832 let Inst{31} = 0;
4833 let Inst{30} = size{0};
4834 let Inst{29-24} = 0b001110;
4835 let Inst{23-22} = size{2-1};
4836 let Inst{21} = 0;
4837 let Inst{20-16} = Rm;
4838 let Inst{15} = 0;
4839 let Inst{14-12} = opc;
4840 let Inst{11-10} = 0b10;
4841 let Inst{9-5} = Rn;
4842 let Inst{4-0} = Rd;
4843}
4844
4845multiclass SIMDZipVector<bits<3>opc, string asm,
4846 SDNode OpNode> {
4847 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
4848 asm, ".8b", OpNode, v8i8>;
4849 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
4850 asm, ".16b", OpNode, v16i8>;
4851 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
4852 asm, ".4h", OpNode, v4i16>;
4853 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
4854 asm, ".8h", OpNode, v8i16>;
4855 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
4856 asm, ".2s", OpNode, v2i32>;
4857 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
4858 asm, ".4s", OpNode, v4i32>;
4859 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
4860 asm, ".2d", OpNode, v2i64>;
4861
4862 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4863 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4864 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4865 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4866 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4867 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4868}
4869
4870//----------------------------------------------------------------------------
4871// AdvSIMD three register scalar instructions
4872//----------------------------------------------------------------------------
4873
4874let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4875class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4876 RegisterClass regtype, string asm,
4877 list<dag> pattern>
4878 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4879 "\t$Rd, $Rn, $Rm", "", pattern>,
4880 Sched<[WriteV]> {
4881 bits<5> Rd;
4882 bits<5> Rn;
4883 bits<5> Rm;
4884 let Inst{31-30} = 0b01;
4885 let Inst{29} = U;
4886 let Inst{28-24} = 0b11110;
4887 let Inst{23-22} = size;
4888 let Inst{21} = 1;
4889 let Inst{20-16} = Rm;
4890 let Inst{15-11} = opcode;
4891 let Inst{10} = 1;
4892 let Inst{9-5} = Rn;
4893 let Inst{4-0} = Rd;
4894}
4895
4896multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4897 SDPatternOperator OpNode> {
4898 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4899 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4900}
4901
4902multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
4903 SDPatternOperator OpNode> {
4904 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4905 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4906 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
4907 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4908 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
4909
4910 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
4911 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
4912 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
4913 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
4914}
4915
4916multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
4917 SDPatternOperator OpNode> {
4918 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
4919 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4920 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4921}
4922
4923multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
4924 SDPatternOperator OpNode = null_frag> {
4925 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4926 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4927 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4928 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4929 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4930 }
4931
4932 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4933 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4934}
4935
4936multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
4937 SDPatternOperator OpNode = null_frag> {
4938 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4939 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4940 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4941 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4942 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
4943 }
4944
4945 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4946 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4947}
4948
4949class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
4950 dag oops, dag iops, string asm, string cstr, list<dag> pat>
4951 : I<oops, iops, asm,
4952 "\t$Rd, $Rn, $Rm", cstr, pat>,
4953 Sched<[WriteV]> {
4954 bits<5> Rd;
4955 bits<5> Rn;
4956 bits<5> Rm;
4957 let Inst{31-30} = 0b01;
4958 let Inst{29} = U;
4959 let Inst{28-24} = 0b11110;
4960 let Inst{23-22} = size;
4961 let Inst{21} = 1;
4962 let Inst{20-16} = Rm;
4963 let Inst{15-11} = opcode;
4964 let Inst{10} = 0;
4965 let Inst{9-5} = Rn;
4966 let Inst{4-0} = Rd;
4967}
4968
4969let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4970multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
4971 SDPatternOperator OpNode = null_frag> {
4972 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
4973 (outs FPR32:$Rd),
4974 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
4975 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
4976 (outs FPR64:$Rd),
4977 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
4978 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
4979}
4980
4981let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4982multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
4983 SDPatternOperator OpNode = null_frag> {
4984 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
4985 (outs FPR32:$dst),
4986 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
4987 asm, "$Rd = $dst", []>;
4988 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
4989 (outs FPR64:$dst),
4990 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
4991 asm, "$Rd = $dst",
4992 [(set (i64 FPR64:$dst),
4993 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
4994}
4995
4996//----------------------------------------------------------------------------
4997// AdvSIMD two register scalar instructions
4998//----------------------------------------------------------------------------
4999
5000let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5001class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5002 RegisterClass regtype, RegisterClass regtype2,
5003 string asm, list<dag> pat>
5004 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5005 "\t$Rd, $Rn", "", pat>,
5006 Sched<[WriteV]> {
5007 bits<5> Rd;
5008 bits<5> Rn;
5009 let Inst{31-30} = 0b01;
5010 let Inst{29} = U;
5011 let Inst{28-24} = 0b11110;
5012 let Inst{23-22} = size;
5013 let Inst{21-17} = 0b10000;
5014 let Inst{16-12} = opcode;
5015 let Inst{11-10} = 0b10;
5016 let Inst{9-5} = Rn;
5017 let Inst{4-0} = Rd;
5018}
5019
5020let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5021class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5022 RegisterClass regtype, RegisterClass regtype2,
5023 string asm, list<dag> pat>
5024 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5025 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5026 Sched<[WriteV]> {
5027 bits<5> Rd;
5028 bits<5> Rn;
5029 let Inst{31-30} = 0b01;
5030 let Inst{29} = U;
5031 let Inst{28-24} = 0b11110;
5032 let Inst{23-22} = size;
5033 let Inst{21-17} = 0b10000;
5034 let Inst{16-12} = opcode;
5035 let Inst{11-10} = 0b10;
5036 let Inst{9-5} = Rn;
5037 let Inst{4-0} = Rd;
5038}
5039
5040
5041let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5042class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5043 RegisterClass regtype, string asm>
5044 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5045 "\t$Rd, $Rn, #0", "", []>,
5046 Sched<[WriteV]> {
5047 bits<5> Rd;
5048 bits<5> Rn;
5049 let Inst{31-30} = 0b01;
5050 let Inst{29} = U;
5051 let Inst{28-24} = 0b11110;
5052 let Inst{23-22} = size;
5053 let Inst{21-17} = 0b10000;
5054 let Inst{16-12} = opcode;
5055 let Inst{11-10} = 0b10;
5056 let Inst{9-5} = Rn;
5057 let Inst{4-0} = Rd;
5058}
5059
5060class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5061 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5062 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5063 Sched<[WriteV]> {
5064 bits<5> Rd;
5065 bits<5> Rn;
5066 let Inst{31-17} = 0b011111100110000;
5067 let Inst{16-12} = opcode;
5068 let Inst{11-10} = 0b10;
5069 let Inst{9-5} = Rn;
5070 let Inst{4-0} = Rd;
5071}
5072
5073multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5074 SDPatternOperator OpNode> {
5075 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5076
5077 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5078 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5079}
5080
5081multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5082 SDPatternOperator OpNode> {
5083 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5084 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5085
5086 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5087 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5088}
5089
5090multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5091 SDPatternOperator OpNode = null_frag> {
5092 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5093 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
Tim Northoverf4810362014-03-31 15:46:17 +00005094
5095 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5096 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005097}
5098
5099multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5100 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5101 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5102}
5103
5104multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5105 SDPatternOperator OpNode> {
5106 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5107 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5108 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5109 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5110}
5111
5112multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5113 SDPatternOperator OpNode = null_frag> {
5114 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5115 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5116 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5117 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5118 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5119 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5120 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5121 }
5122
5123 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5124 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5125}
5126
Tim Northover00ed9962014-03-29 10:18:08 +00005127multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5128 Intrinsic OpNode> {
Tim Northover903814c2014-03-31 15:46:26 +00005129 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5130 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5131 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5132 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5133 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5134 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5135 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5136 }
5137
5138 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5139 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005140}
5141
5142
5143
5144let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5145multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5146 SDPatternOperator OpNode = null_frag> {
5147 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5148 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5149 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5150 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5151}
5152
5153//----------------------------------------------------------------------------
5154// AdvSIMD scalar pairwise instructions
5155//----------------------------------------------------------------------------
5156
5157let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5158class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5159 RegisterOperand regtype, RegisterOperand vectype,
5160 string asm, string kind>
5161 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5162 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5163 Sched<[WriteV]> {
5164 bits<5> Rd;
5165 bits<5> Rn;
5166 let Inst{31-30} = 0b01;
5167 let Inst{29} = U;
5168 let Inst{28-24} = 0b11110;
5169 let Inst{23-22} = size;
5170 let Inst{21-17} = 0b11000;
5171 let Inst{16-12} = opcode;
5172 let Inst{11-10} = 0b10;
5173 let Inst{9-5} = Rn;
5174 let Inst{4-0} = Rd;
5175}
5176
5177multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5178 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5179 asm, ".2d">;
5180}
5181
5182multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5183 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5184 asm, ".2s">;
5185 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5186 asm, ".2d">;
5187}
5188
5189//----------------------------------------------------------------------------
5190// AdvSIMD across lanes instructions
5191//----------------------------------------------------------------------------
5192
5193let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5194class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5195 RegisterClass regtype, RegisterOperand vectype,
5196 string asm, string kind, list<dag> pattern>
5197 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5198 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5199 Sched<[WriteV]> {
5200 bits<5> Rd;
5201 bits<5> Rn;
5202 let Inst{31} = 0;
5203 let Inst{30} = Q;
5204 let Inst{29} = U;
5205 let Inst{28-24} = 0b01110;
5206 let Inst{23-22} = size;
5207 let Inst{21-17} = 0b11000;
5208 let Inst{16-12} = opcode;
5209 let Inst{11-10} = 0b10;
5210 let Inst{9-5} = Rn;
5211 let Inst{4-0} = Rd;
5212}
5213
5214multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5215 string asm> {
5216 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5217 asm, ".8b", []>;
5218 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5219 asm, ".16b", []>;
5220 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5221 asm, ".4h", []>;
5222 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5223 asm, ".8h", []>;
5224 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5225 asm, ".4s", []>;
5226}
5227
5228multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5229 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5230 asm, ".8b", []>;
5231 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5232 asm, ".16b", []>;
5233 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5234 asm, ".4h", []>;
5235 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5236 asm, ".8h", []>;
5237 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5238 asm, ".4s", []>;
5239}
5240
5241multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5242 Intrinsic intOp> {
5243 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5244 asm, ".4s",
5245 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5246}
5247
5248//----------------------------------------------------------------------------
5249// AdvSIMD INS/DUP instructions
5250//----------------------------------------------------------------------------
5251
5252// FIXME: There has got to be a better way to factor these. ugh.
5253
5254class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5255 string operands, string constraints, list<dag> pattern>
5256 : I<outs, ins, asm, operands, constraints, pattern>,
5257 Sched<[WriteV]> {
5258 bits<5> Rd;
5259 bits<5> Rn;
5260 let Inst{31} = 0;
5261 let Inst{30} = Q;
5262 let Inst{29} = op;
5263 let Inst{28-21} = 0b01110000;
5264 let Inst{15} = 0;
5265 let Inst{10} = 1;
5266 let Inst{9-5} = Rn;
5267 let Inst{4-0} = Rd;
5268}
5269
5270class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5271 RegisterOperand vecreg, RegisterClass regtype>
5272 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5273 "{\t$Rd" # size # ", $Rn" #
5274 "|" # size # "\t$Rd, $Rn}", "",
5275 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5276 let Inst{20-16} = imm5;
5277 let Inst{14-11} = 0b0001;
5278}
5279
5280class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5281 ValueType vectype, ValueType insreg,
5282 RegisterOperand vecreg, Operand idxtype,
5283 ValueType elttype, SDNode OpNode>
5284 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5285 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5286 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5287 [(set (vectype vecreg:$Rd),
5288 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5289 let Inst{14-11} = 0b0000;
5290}
5291
5292class SIMDDup64FromElement
5293 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5294 VectorIndexD, i64, ARM64duplane64> {
5295 bits<1> idx;
5296 let Inst{20} = idx;
5297 let Inst{19-16} = 0b1000;
5298}
5299
5300class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5301 RegisterOperand vecreg>
5302 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5303 VectorIndexS, i64, ARM64duplane32> {
5304 bits<2> idx;
5305 let Inst{20-19} = idx;
5306 let Inst{18-16} = 0b100;
5307}
5308
5309class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5310 RegisterOperand vecreg>
5311 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5312 VectorIndexH, i64, ARM64duplane16> {
5313 bits<3> idx;
5314 let Inst{20-18} = idx;
5315 let Inst{17-16} = 0b10;
5316}
5317
5318class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5319 RegisterOperand vecreg>
5320 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5321 VectorIndexB, i64, ARM64duplane8> {
5322 bits<4> idx;
5323 let Inst{20-17} = idx;
5324 let Inst{16} = 1;
5325}
5326
5327class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5328 Operand idxtype, string asm, list<dag> pattern>
5329 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5330 "{\t$Rd, $Rn" # size # "$idx" #
5331 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5332 let Inst{14-11} = imm4;
5333}
5334
5335class SIMDSMov<bit Q, string size, RegisterClass regtype,
5336 Operand idxtype>
5337 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5338class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5339 Operand idxtype>
5340 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5341 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5342
5343class SIMDMovAlias<string asm, string size, Instruction inst,
5344 RegisterClass regtype, Operand idxtype>
5345 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5346 "|" # size # "\t$dst, $src$idx}",
5347 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5348
5349multiclass SMov {
5350 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5351 bits<4> idx;
5352 let Inst{20-17} = idx;
5353 let Inst{16} = 1;
5354 }
5355 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5356 bits<4> idx;
5357 let Inst{20-17} = idx;
5358 let Inst{16} = 1;
5359 }
5360 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5361 bits<3> idx;
5362 let Inst{20-18} = idx;
5363 let Inst{17-16} = 0b10;
5364 }
5365 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5366 bits<3> idx;
5367 let Inst{20-18} = idx;
5368 let Inst{17-16} = 0b10;
5369 }
5370 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5371 bits<2> idx;
5372 let Inst{20-19} = idx;
5373 let Inst{18-16} = 0b100;
5374 }
5375}
5376
5377multiclass UMov {
5378 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5379 bits<4> idx;
5380 let Inst{20-17} = idx;
5381 let Inst{16} = 1;
5382 }
5383 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5384 bits<3> idx;
5385 let Inst{20-18} = idx;
5386 let Inst{17-16} = 0b10;
5387 }
5388 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5389 bits<2> idx;
5390 let Inst{20-19} = idx;
5391 let Inst{18-16} = 0b100;
5392 }
5393 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5394 bits<1> idx;
5395 let Inst{20} = idx;
5396 let Inst{19-16} = 0b1000;
5397 }
5398 def : SIMDMovAlias<"mov", ".s",
5399 !cast<Instruction>(NAME#"vi32"),
5400 GPR32, VectorIndexS>;
5401 def : SIMDMovAlias<"mov", ".d",
5402 !cast<Instruction>(NAME#"vi64"),
5403 GPR64, VectorIndexD>;
5404}
5405
5406class SIMDInsFromMain<string size, ValueType vectype,
5407 RegisterClass regtype, Operand idxtype>
5408 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5409 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5410 "{\t$Rd" # size # "$idx, $Rn" #
5411 "|" # size # "\t$Rd$idx, $Rn}",
5412 "$Rd = $dst",
5413 [(set V128:$dst,
5414 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5415 let Inst{14-11} = 0b0011;
5416}
5417
5418class SIMDInsFromElement<string size, ValueType vectype,
5419 ValueType elttype, Operand idxtype>
5420 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5421 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5422 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5423 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5424 "$Rd = $dst",
5425 [(set V128:$dst,
5426 (vector_insert
5427 (vectype V128:$Rd),
5428 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5429 idxtype:$idx))]>;
5430
5431class SIMDInsMainMovAlias<string size, Instruction inst,
5432 RegisterClass regtype, Operand idxtype>
5433 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5434 "|" # size #"\t$dst$idx, $src}",
5435 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5436class SIMDInsElementMovAlias<string size, Instruction inst,
5437 Operand idxtype>
5438 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5439 # "|" # size #" $dst$idx, $src$idx2}",
5440 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5441
5442
5443multiclass SIMDIns {
5444 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5445 bits<4> idx;
5446 let Inst{20-17} = idx;
5447 let Inst{16} = 1;
5448 }
5449 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5450 bits<3> idx;
5451 let Inst{20-18} = idx;
5452 let Inst{17-16} = 0b10;
5453 }
5454 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5455 bits<2> idx;
5456 let Inst{20-19} = idx;
5457 let Inst{18-16} = 0b100;
5458 }
5459 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5460 bits<1> idx;
5461 let Inst{20} = idx;
5462 let Inst{19-16} = 0b1000;
5463 }
5464
5465 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5466 bits<4> idx;
5467 bits<4> idx2;
5468 let Inst{20-17} = idx;
5469 let Inst{16} = 1;
5470 let Inst{14-11} = idx2;
5471 }
5472 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5473 bits<3> idx;
5474 bits<3> idx2;
5475 let Inst{20-18} = idx;
5476 let Inst{17-16} = 0b10;
5477 let Inst{14-12} = idx2;
5478 let Inst{11} = 0;
5479 }
5480 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5481 bits<2> idx;
5482 bits<2> idx2;
5483 let Inst{20-19} = idx;
5484 let Inst{18-16} = 0b100;
5485 let Inst{14-13} = idx2;
5486 let Inst{12-11} = 0;
5487 }
5488 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5489 bits<1> idx;
5490 bits<1> idx2;
5491 let Inst{20} = idx;
5492 let Inst{19-16} = 0b1000;
5493 let Inst{14} = idx2;
5494 let Inst{13-11} = 0;
5495 }
5496
5497 // For all forms of the INS instruction, the "mov" mnemonic is the
5498 // preferred alias. Why they didn't just call the instruction "mov" in
5499 // the first place is a very good question indeed...
5500 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5501 GPR32, VectorIndexB>;
5502 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5503 GPR32, VectorIndexH>;
5504 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5505 GPR32, VectorIndexS>;
5506 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5507 GPR64, VectorIndexD>;
5508
5509 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5510 VectorIndexB>;
5511 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5512 VectorIndexH>;
5513 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5514 VectorIndexS>;
5515 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5516 VectorIndexD>;
5517}
5518
5519//----------------------------------------------------------------------------
5520// AdvSIMD TBL/TBX
5521//----------------------------------------------------------------------------
5522
5523let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5524class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5525 RegisterOperand listtype, string asm, string kind>
5526 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5527 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5528 Sched<[WriteV]> {
5529 bits<5> Vd;
5530 bits<5> Vn;
5531 bits<5> Vm;
5532 let Inst{31} = 0;
5533 let Inst{30} = Q;
5534 let Inst{29-21} = 0b001110000;
5535 let Inst{20-16} = Vm;
5536 let Inst{15} = 0;
5537 let Inst{14-13} = len;
5538 let Inst{12} = op;
5539 let Inst{11-10} = 0b00;
5540 let Inst{9-5} = Vn;
5541 let Inst{4-0} = Vd;
5542}
5543
5544let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5545class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5546 RegisterOperand listtype, string asm, string kind>
5547 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5548 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5549 Sched<[WriteV]> {
5550 bits<5> Vd;
5551 bits<5> Vn;
5552 bits<5> Vm;
5553 let Inst{31} = 0;
5554 let Inst{30} = Q;
5555 let Inst{29-21} = 0b001110000;
5556 let Inst{20-16} = Vm;
5557 let Inst{15} = 0;
5558 let Inst{14-13} = len;
5559 let Inst{12} = op;
5560 let Inst{11-10} = 0b00;
5561 let Inst{9-5} = Vn;
5562 let Inst{4-0} = Vd;
5563}
5564
5565class SIMDTableLookupAlias<string asm, Instruction inst,
5566 RegisterOperand vectype, RegisterOperand listtype>
5567 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5568 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5569
5570multiclass SIMDTableLookup<bit op, string asm> {
5571 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5572 asm, ".8b">;
5573 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5574 asm, ".8b">;
5575 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5576 asm, ".8b">;
5577 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5578 asm, ".8b">;
5579 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5580 asm, ".16b">;
5581 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5582 asm, ".16b">;
5583 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5584 asm, ".16b">;
5585 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5586 asm, ".16b">;
5587
5588 def : SIMDTableLookupAlias<asm # ".8b",
5589 !cast<Instruction>(NAME#"v8i8One"),
5590 V64, VecListOne128>;
5591 def : SIMDTableLookupAlias<asm # ".8b",
5592 !cast<Instruction>(NAME#"v8i8Two"),
5593 V64, VecListTwo128>;
5594 def : SIMDTableLookupAlias<asm # ".8b",
5595 !cast<Instruction>(NAME#"v8i8Three"),
5596 V64, VecListThree128>;
5597 def : SIMDTableLookupAlias<asm # ".8b",
5598 !cast<Instruction>(NAME#"v8i8Four"),
5599 V64, VecListFour128>;
5600 def : SIMDTableLookupAlias<asm # ".16b",
5601 !cast<Instruction>(NAME#"v16i8One"),
5602 V128, VecListOne128>;
5603 def : SIMDTableLookupAlias<asm # ".16b",
5604 !cast<Instruction>(NAME#"v16i8Two"),
5605 V128, VecListTwo128>;
5606 def : SIMDTableLookupAlias<asm # ".16b",
5607 !cast<Instruction>(NAME#"v16i8Three"),
5608 V128, VecListThree128>;
5609 def : SIMDTableLookupAlias<asm # ".16b",
5610 !cast<Instruction>(NAME#"v16i8Four"),
5611 V128, VecListFour128>;
5612}
5613
5614multiclass SIMDTableLookupTied<bit op, string asm> {
5615 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5616 asm, ".8b">;
5617 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5618 asm, ".8b">;
5619 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5620 asm, ".8b">;
5621 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5622 asm, ".8b">;
5623 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5624 asm, ".16b">;
5625 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5626 asm, ".16b">;
5627 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5628 asm, ".16b">;
5629 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5630 asm, ".16b">;
5631
5632 def : SIMDTableLookupAlias<asm # ".8b",
5633 !cast<Instruction>(NAME#"v8i8One"),
5634 V64, VecListOne128>;
5635 def : SIMDTableLookupAlias<asm # ".8b",
5636 !cast<Instruction>(NAME#"v8i8Two"),
5637 V64, VecListTwo128>;
5638 def : SIMDTableLookupAlias<asm # ".8b",
5639 !cast<Instruction>(NAME#"v8i8Three"),
5640 V64, VecListThree128>;
5641 def : SIMDTableLookupAlias<asm # ".8b",
5642 !cast<Instruction>(NAME#"v8i8Four"),
5643 V64, VecListFour128>;
5644 def : SIMDTableLookupAlias<asm # ".16b",
5645 !cast<Instruction>(NAME#"v16i8One"),
5646 V128, VecListOne128>;
5647 def : SIMDTableLookupAlias<asm # ".16b",
5648 !cast<Instruction>(NAME#"v16i8Two"),
5649 V128, VecListTwo128>;
5650 def : SIMDTableLookupAlias<asm # ".16b",
5651 !cast<Instruction>(NAME#"v16i8Three"),
5652 V128, VecListThree128>;
5653 def : SIMDTableLookupAlias<asm # ".16b",
5654 !cast<Instruction>(NAME#"v16i8Four"),
5655 V128, VecListFour128>;
5656}
5657
5658
5659//----------------------------------------------------------------------------
5660// AdvSIMD scalar CPY
5661//----------------------------------------------------------------------------
5662let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5663class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5664 string kind, Operand idxtype>
5665 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5666 "{\t$dst, $src" # kind # "$idx" #
5667 "|\t$dst, $src$idx}", "", []>,
5668 Sched<[WriteV]> {
5669 bits<5> dst;
5670 bits<5> src;
5671 let Inst{31-21} = 0b01011110000;
5672 let Inst{15-10} = 0b000001;
5673 let Inst{9-5} = src;
5674 let Inst{4-0} = dst;
5675}
5676
5677class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5678 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5679 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5680 # "|\t$dst, $src$index}",
5681 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5682
5683
5684multiclass SIMDScalarCPY<string asm> {
5685 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5686 bits<4> idx;
5687 let Inst{20-17} = idx;
5688 let Inst{16} = 1;
5689 }
5690 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5691 bits<3> idx;
5692 let Inst{20-18} = idx;
5693 let Inst{17-16} = 0b10;
5694 }
5695 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5696 bits<2> idx;
5697 let Inst{20-19} = idx;
5698 let Inst{18-16} = 0b100;
5699 }
5700 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5701 bits<1> idx;
5702 let Inst{20} = idx;
5703 let Inst{19-16} = 0b1000;
5704 }
5705
5706 // 'DUP' mnemonic aliases.
5707 def : SIMDScalarCPYAlias<"dup", ".b",
5708 !cast<Instruction>(NAME#"i8"),
5709 FPR8, V128, VectorIndexB>;
5710 def : SIMDScalarCPYAlias<"dup", ".h",
5711 !cast<Instruction>(NAME#"i16"),
5712 FPR16, V128, VectorIndexH>;
5713 def : SIMDScalarCPYAlias<"dup", ".s",
5714 !cast<Instruction>(NAME#"i32"),
5715 FPR32, V128, VectorIndexS>;
5716 def : SIMDScalarCPYAlias<"dup", ".d",
5717 !cast<Instruction>(NAME#"i64"),
5718 FPR64, V128, VectorIndexD>;
5719}
5720
5721//----------------------------------------------------------------------------
5722// AdvSIMD modified immediate instructions
5723//----------------------------------------------------------------------------
5724
5725class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5726 string asm, string op_string,
5727 string cstr, list<dag> pattern>
5728 : I<oops, iops, asm, op_string, cstr, pattern>,
5729 Sched<[WriteV]> {
5730 bits<5> Rd;
5731 bits<8> imm8;
5732 let Inst{31} = 0;
5733 let Inst{30} = Q;
5734 let Inst{29} = op;
5735 let Inst{28-19} = 0b0111100000;
5736 let Inst{18-16} = imm8{7-5};
5737 let Inst{11-10} = 0b01;
5738 let Inst{9-5} = imm8{4-0};
5739 let Inst{4-0} = Rd;
5740}
5741
5742class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5743 Operand immtype, dag opt_shift_iop,
5744 string opt_shift, string asm, string kind,
5745 list<dag> pattern>
5746 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5747 !con((ins immtype:$imm8), opt_shift_iop), asm,
5748 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5749 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5750 "", pattern> {
5751 let DecoderMethod = "DecodeModImmInstruction";
5752}
5753
5754class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5755 Operand immtype, dag opt_shift_iop,
5756 string opt_shift, string asm, string kind,
5757 list<dag> pattern>
5758 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5759 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5760 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5761 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5762 "$Rd = $dst", pattern> {
5763 let DecoderMethod = "DecodeModImmTiedInstruction";
5764}
5765
5766class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5767 RegisterOperand vectype, string asm,
5768 string kind, list<dag> pattern>
5769 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5770 (ins logical_vec_shift:$shift),
5771 "$shift", asm, kind, pattern> {
5772 bits<2> shift;
5773 let Inst{15} = b15_b12{1};
5774 let Inst{14-13} = shift;
5775 let Inst{12} = b15_b12{0};
5776}
5777
5778class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5779 RegisterOperand vectype, string asm,
5780 string kind, list<dag> pattern>
5781 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5782 (ins logical_vec_shift:$shift),
5783 "$shift", asm, kind, pattern> {
5784 bits<2> shift;
5785 let Inst{15} = b15_b12{1};
5786 let Inst{14-13} = shift;
5787 let Inst{12} = b15_b12{0};
5788}
5789
5790
5791class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5792 RegisterOperand vectype, string asm,
5793 string kind, list<dag> pattern>
5794 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5795 (ins logical_vec_hw_shift:$shift),
5796 "$shift", asm, kind, pattern> {
5797 bits<2> shift;
5798 let Inst{15} = b15_b12{1};
5799 let Inst{14} = 0;
5800 let Inst{13} = shift{0};
5801 let Inst{12} = b15_b12{0};
5802}
5803
5804class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5805 RegisterOperand vectype, string asm,
5806 string kind, list<dag> pattern>
5807 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5808 (ins logical_vec_hw_shift:$shift),
5809 "$shift", asm, kind, pattern> {
5810 bits<2> shift;
5811 let Inst{15} = b15_b12{1};
5812 let Inst{14} = 0;
5813 let Inst{13} = shift{0};
5814 let Inst{12} = b15_b12{0};
5815}
5816
5817multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5818 string asm> {
5819 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5820 asm, ".4h", []>;
5821 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5822 asm, ".8h", []>;
5823
5824 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5825 asm, ".2s", []>;
5826 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5827 asm, ".4s", []>;
5828}
5829
5830multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5831 bits<2> w_cmode, string asm,
5832 SDNode OpNode> {
5833 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5834 asm, ".4h",
5835 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5836 imm0_255:$imm8,
5837 (i32 imm:$shift)))]>;
5838 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5839 asm, ".8h",
5840 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5841 imm0_255:$imm8,
5842 (i32 imm:$shift)))]>;
5843
5844 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5845 asm, ".2s",
5846 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5847 imm0_255:$imm8,
5848 (i32 imm:$shift)))]>;
5849 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5850 asm, ".4s",
5851 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5852 imm0_255:$imm8,
5853 (i32 imm:$shift)))]>;
5854}
5855
5856class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5857 RegisterOperand vectype, string asm,
5858 string kind, list<dag> pattern>
5859 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5860 (ins move_vec_shift:$shift),
5861 "$shift", asm, kind, pattern> {
5862 bits<1> shift;
5863 let Inst{15-13} = cmode{3-1};
5864 let Inst{12} = shift;
5865}
5866
5867class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5868 RegisterOperand vectype,
5869 Operand imm_type, string asm,
5870 string kind, list<dag> pattern>
5871 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5872 asm, kind, pattern> {
5873 let Inst{15-12} = cmode;
5874}
5875
5876class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5877 list<dag> pattern>
5878 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5879 "\t$Rd, $imm8", "", pattern> {
5880 let Inst{15-12} = cmode;
5881 let DecoderMethod = "DecodeModImmInstruction";
5882}
5883
5884//----------------------------------------------------------------------------
5885// AdvSIMD indexed element
5886//----------------------------------------------------------------------------
5887
5888let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5889class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5890 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5891 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5892 string apple_kind, string dst_kind, string lhs_kind,
5893 string rhs_kind, list<dag> pattern>
5894 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5895 asm,
5896 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5897 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5898 Sched<[WriteV]> {
5899 bits<5> Rd;
5900 bits<5> Rn;
5901 bits<5> Rm;
5902
5903 let Inst{31} = 0;
5904 let Inst{30} = Q;
5905 let Inst{29} = U;
5906 let Inst{28} = Scalar;
5907 let Inst{27-24} = 0b1111;
5908 let Inst{23-22} = size;
5909 // Bit 21 must be set by the derived class.
5910 let Inst{20-16} = Rm;
5911 let Inst{15-12} = opc;
5912 // Bit 11 must be set by the derived class.
5913 let Inst{10} = 0;
5914 let Inst{9-5} = Rn;
5915 let Inst{4-0} = Rd;
5916}
5917
5918let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5919class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5920 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5921 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5922 string apple_kind, string dst_kind, string lhs_kind,
5923 string rhs_kind, list<dag> pattern>
5924 : I<(outs dst_reg:$dst),
5925 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
5926 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5927 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
5928 Sched<[WriteV]> {
5929 bits<5> Rd;
5930 bits<5> Rn;
5931 bits<5> Rm;
5932
5933 let Inst{31} = 0;
5934 let Inst{30} = Q;
5935 let Inst{29} = U;
5936 let Inst{28} = Scalar;
5937 let Inst{27-24} = 0b1111;
5938 let Inst{23-22} = size;
5939 // Bit 21 must be set by the derived class.
5940 let Inst{20-16} = Rm;
5941 let Inst{15-12} = opc;
5942 // Bit 11 must be set by the derived class.
5943 let Inst{10} = 0;
5944 let Inst{9-5} = Rn;
5945 let Inst{4-0} = Rd;
5946}
5947
5948multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
5949 SDPatternOperator OpNode> {
5950 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
5951 V64, V64,
5952 V128, VectorIndexS,
5953 asm, ".2s", ".2s", ".2s", ".s",
5954 [(set (v2f32 V64:$Rd),
5955 (OpNode (v2f32 V64:$Rn),
5956 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
5957 bits<2> idx;
5958 let Inst{11} = idx{1};
5959 let Inst{21} = idx{0};
5960 }
5961
5962 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
5963 V128, V128,
5964 V128, VectorIndexS,
5965 asm, ".4s", ".4s", ".4s", ".s",
5966 [(set (v4f32 V128:$Rd),
5967 (OpNode (v4f32 V128:$Rn),
5968 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
5969 bits<2> idx;
5970 let Inst{11} = idx{1};
5971 let Inst{21} = idx{0};
5972 }
5973
5974 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
5975 V128, V128,
5976 V128, VectorIndexD,
5977 asm, ".2d", ".2d", ".2d", ".d",
5978 [(set (v2f64 V128:$Rd),
5979 (OpNode (v2f64 V128:$Rn),
5980 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
5981 bits<1> idx;
5982 let Inst{11} = idx{0};
5983 let Inst{21} = 0;
5984 }
5985
5986 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
5987 FPR32Op, FPR32Op, V128, VectorIndexS,
5988 asm, ".s", "", "", ".s",
5989 [(set (f32 FPR32Op:$Rd),
5990 (OpNode (f32 FPR32Op:$Rn),
5991 (f32 (vector_extract (v4f32 V128:$Rm),
5992 VectorIndexS:$idx))))]> {
5993 bits<2> idx;
5994 let Inst{11} = idx{1};
5995 let Inst{21} = idx{0};
5996 }
5997
5998 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
5999 FPR64Op, FPR64Op, V128, VectorIndexD,
6000 asm, ".d", "", "", ".d",
6001 [(set (f64 FPR64Op:$Rd),
6002 (OpNode (f64 FPR64Op:$Rn),
6003 (f64 (vector_extract (v2f64 V128:$Rm),
6004 VectorIndexD:$idx))))]> {
6005 bits<1> idx;
6006 let Inst{11} = idx{0};
6007 let Inst{21} = 0;
6008 }
6009}
6010
6011multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6012 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6013 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6014 (ARM64duplane32 (v4f32 V128:$Rm),
6015 VectorIndexS:$idx))),
6016 (!cast<Instruction>(INST # v2i32_indexed)
6017 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6018 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6019 (ARM64dup (f32 FPR32Op:$Rm)))),
6020 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6021 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6022
6023
6024 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6025 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6026 (ARM64duplane32 (v4f32 V128:$Rm),
6027 VectorIndexS:$idx))),
6028 (!cast<Instruction>(INST # "v4i32_indexed")
6029 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6030 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6031 (ARM64dup (f32 FPR32Op:$Rm)))),
6032 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6033 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6034
6035 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6036 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6037 (ARM64duplane64 (v2f64 V128:$Rm),
6038 VectorIndexD:$idx))),
6039 (!cast<Instruction>(INST # "v2i64_indexed")
6040 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6041 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6042 (ARM64dup (f64 FPR64Op:$Rm)))),
6043 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6044 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6045
6046 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6047 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6048 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6049 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6050 V128:$Rm, VectorIndexS:$idx)>;
6051 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6052 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6053 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6054 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6055
6056 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6057 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6058 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6059 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6060 V128:$Rm, VectorIndexD:$idx)>;
6061}
6062
6063multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6064 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6065 V128, VectorIndexS,
6066 asm, ".2s", ".2s", ".2s", ".s", []> {
6067 bits<2> idx;
6068 let Inst{11} = idx{1};
6069 let Inst{21} = idx{0};
6070 }
6071
6072 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6073 V128, V128,
6074 V128, VectorIndexS,
6075 asm, ".4s", ".4s", ".4s", ".s", []> {
6076 bits<2> idx;
6077 let Inst{11} = idx{1};
6078 let Inst{21} = idx{0};
6079 }
6080
6081 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6082 V128, V128,
6083 V128, VectorIndexD,
6084 asm, ".2d", ".2d", ".2d", ".d", []> {
6085 bits<1> idx;
6086 let Inst{11} = idx{0};
6087 let Inst{21} = 0;
6088 }
6089
6090
6091 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6092 FPR32Op, FPR32Op, V128, VectorIndexS,
6093 asm, ".s", "", "", ".s", []> {
6094 bits<2> idx;
6095 let Inst{11} = idx{1};
6096 let Inst{21} = idx{0};
6097 }
6098
6099 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6100 FPR64Op, FPR64Op, V128, VectorIndexD,
6101 asm, ".d", "", "", ".d", []> {
6102 bits<1> idx;
6103 let Inst{11} = idx{0};
6104 let Inst{21} = 0;
6105 }
6106}
6107
6108multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6109 SDPatternOperator OpNode> {
6110 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6111 V128_lo, VectorIndexH,
6112 asm, ".4h", ".4h", ".4h", ".h",
6113 [(set (v4i16 V64:$Rd),
6114 (OpNode (v4i16 V64:$Rn),
6115 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6116 bits<3> idx;
6117 let Inst{11} = idx{2};
6118 let Inst{21} = idx{1};
6119 let Inst{20} = idx{0};
6120 }
6121
6122 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6123 V128, V128,
6124 V128_lo, VectorIndexH,
6125 asm, ".8h", ".8h", ".8h", ".h",
6126 [(set (v8i16 V128:$Rd),
6127 (OpNode (v8i16 V128:$Rn),
6128 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6129 bits<3> idx;
6130 let Inst{11} = idx{2};
6131 let Inst{21} = idx{1};
6132 let Inst{20} = idx{0};
6133 }
6134
6135 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6136 V64, V64,
6137 V128, VectorIndexS,
6138 asm, ".2s", ".2s", ".2s", ".s",
6139 [(set (v2i32 V64:$Rd),
6140 (OpNode (v2i32 V64:$Rn),
6141 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6142 bits<2> idx;
6143 let Inst{11} = idx{1};
6144 let Inst{21} = idx{0};
6145 }
6146
6147 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6148 V128, V128,
6149 V128, VectorIndexS,
6150 asm, ".4s", ".4s", ".4s", ".s",
6151 [(set (v4i32 V128:$Rd),
6152 (OpNode (v4i32 V128:$Rn),
6153 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6154 bits<2> idx;
6155 let Inst{11} = idx{1};
6156 let Inst{21} = idx{0};
6157 }
6158
6159 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6160 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6161 asm, ".h", "", "", ".h", []> {
6162 bits<3> idx;
6163 let Inst{11} = idx{2};
6164 let Inst{21} = idx{1};
6165 let Inst{20} = idx{0};
6166 }
6167
6168 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6169 FPR32Op, FPR32Op, V128, VectorIndexS,
6170 asm, ".s", "", "", ".s",
6171 [(set (i32 FPR32Op:$Rd),
6172 (OpNode FPR32Op:$Rn,
6173 (i32 (vector_extract (v4i32 V128:$Rm),
6174 VectorIndexS:$idx))))]> {
6175 bits<2> idx;
6176 let Inst{11} = idx{1};
6177 let Inst{21} = idx{0};
6178 }
6179}
6180
6181multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6182 SDPatternOperator OpNode> {
6183 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6184 V64, V64,
6185 V128_lo, VectorIndexH,
6186 asm, ".4h", ".4h", ".4h", ".h",
6187 [(set (v4i16 V64:$Rd),
6188 (OpNode (v4i16 V64:$Rn),
6189 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6190 bits<3> idx;
6191 let Inst{11} = idx{2};
6192 let Inst{21} = idx{1};
6193 let Inst{20} = idx{0};
6194 }
6195
6196 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6197 V128, V128,
6198 V128_lo, VectorIndexH,
6199 asm, ".8h", ".8h", ".8h", ".h",
6200 [(set (v8i16 V128:$Rd),
6201 (OpNode (v8i16 V128:$Rn),
6202 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6203 bits<3> idx;
6204 let Inst{11} = idx{2};
6205 let Inst{21} = idx{1};
6206 let Inst{20} = idx{0};
6207 }
6208
6209 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6210 V64, V64,
6211 V128, VectorIndexS,
6212 asm, ".2s", ".2s", ".2s", ".s",
6213 [(set (v2i32 V64:$Rd),
6214 (OpNode (v2i32 V64:$Rn),
6215 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6216 bits<2> idx;
6217 let Inst{11} = idx{1};
6218 let Inst{21} = idx{0};
6219 }
6220
6221 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6222 V128, V128,
6223 V128, VectorIndexS,
6224 asm, ".4s", ".4s", ".4s", ".s",
6225 [(set (v4i32 V128:$Rd),
6226 (OpNode (v4i32 V128:$Rn),
6227 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6228 bits<2> idx;
6229 let Inst{11} = idx{1};
6230 let Inst{21} = idx{0};
6231 }
6232}
6233
6234multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6235 SDPatternOperator OpNode> {
6236 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6237 V128_lo, VectorIndexH,
6238 asm, ".4h", ".4h", ".4h", ".h",
6239 [(set (v4i16 V64:$dst),
6240 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6241 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6242 bits<3> idx;
6243 let Inst{11} = idx{2};
6244 let Inst{21} = idx{1};
6245 let Inst{20} = idx{0};
6246 }
6247
6248 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6249 V128, V128,
6250 V128_lo, VectorIndexH,
6251 asm, ".8h", ".8h", ".8h", ".h",
6252 [(set (v8i16 V128:$dst),
6253 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6254 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6255 bits<3> idx;
6256 let Inst{11} = idx{2};
6257 let Inst{21} = idx{1};
6258 let Inst{20} = idx{0};
6259 }
6260
6261 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6262 V64, V64,
6263 V128, VectorIndexS,
6264 asm, ".2s", ".2s", ".2s", ".s",
6265 [(set (v2i32 V64:$dst),
6266 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6267 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6268 bits<2> idx;
6269 let Inst{11} = idx{1};
6270 let Inst{21} = idx{0};
6271 }
6272
6273 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6274 V128, V128,
6275 V128, VectorIndexS,
6276 asm, ".4s", ".4s", ".4s", ".s",
6277 [(set (v4i32 V128:$dst),
6278 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6279 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6280 bits<2> idx;
6281 let Inst{11} = idx{1};
6282 let Inst{21} = idx{0};
6283 }
6284}
6285
6286multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6287 SDPatternOperator OpNode> {
6288 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6289 V128, V64,
6290 V128_lo, VectorIndexH,
6291 asm, ".4s", ".4s", ".4h", ".h",
6292 [(set (v4i32 V128:$Rd),
6293 (OpNode (v4i16 V64:$Rn),
6294 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6295 bits<3> idx;
6296 let Inst{11} = idx{2};
6297 let Inst{21} = idx{1};
6298 let Inst{20} = idx{0};
6299 }
6300
6301 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6302 V128, V128,
6303 V128_lo, VectorIndexH,
6304 asm#"2", ".4s", ".4s", ".8h", ".h",
6305 [(set (v4i32 V128:$Rd),
6306 (OpNode (extract_high_v8i16 V128:$Rn),
6307 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6308 VectorIndexH:$idx))))]> {
6309
6310 bits<3> idx;
6311 let Inst{11} = idx{2};
6312 let Inst{21} = idx{1};
6313 let Inst{20} = idx{0};
6314 }
6315
6316 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6317 V128, V64,
6318 V128, VectorIndexS,
6319 asm, ".2d", ".2d", ".2s", ".s",
6320 [(set (v2i64 V128:$Rd),
6321 (OpNode (v2i32 V64:$Rn),
6322 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6323 bits<2> idx;
6324 let Inst{11} = idx{1};
6325 let Inst{21} = idx{0};
6326 }
6327
6328 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6329 V128, V128,
6330 V128, VectorIndexS,
6331 asm#"2", ".2d", ".2d", ".4s", ".s",
6332 [(set (v2i64 V128:$Rd),
6333 (OpNode (extract_high_v4i32 V128:$Rn),
6334 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6335 VectorIndexS:$idx))))]> {
6336 bits<2> idx;
6337 let Inst{11} = idx{1};
6338 let Inst{21} = idx{0};
6339 }
6340
6341 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6342 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6343 asm, ".h", "", "", ".h", []> {
6344 bits<3> idx;
6345 let Inst{11} = idx{2};
6346 let Inst{21} = idx{1};
6347 let Inst{20} = idx{0};
6348 }
6349
6350 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6351 FPR64Op, FPR32Op, V128, VectorIndexS,
6352 asm, ".s", "", "", ".s", []> {
6353 bits<2> idx;
6354 let Inst{11} = idx{1};
6355 let Inst{21} = idx{0};
6356 }
6357}
6358
6359multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6360 SDPatternOperator Accum> {
6361 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6362 V128, V64,
6363 V128_lo, VectorIndexH,
6364 asm, ".4s", ".4s", ".4h", ".h",
6365 [(set (v4i32 V128:$dst),
6366 (Accum (v4i32 V128:$Rd),
6367 (v4i32 (int_arm64_neon_sqdmull
6368 (v4i16 V64:$Rn),
6369 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6370 VectorIndexH:$idx))))))]> {
6371 bits<3> idx;
6372 let Inst{11} = idx{2};
6373 let Inst{21} = idx{1};
6374 let Inst{20} = idx{0};
6375 }
6376
6377 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6378 // intermediate EXTRACT_SUBREG would be untyped.
6379 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6380 (i32 (vector_extract (v4i32
6381 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6382 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6383 VectorIndexH:$idx)))),
6384 (i64 0))))),
6385 (EXTRACT_SUBREG
6386 (!cast<Instruction>(NAME # v4i16_indexed)
6387 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6388 V128_lo:$Rm, VectorIndexH:$idx),
6389 ssub)>;
6390
6391 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6392 V128, V128,
6393 V128_lo, VectorIndexH,
6394 asm#"2", ".4s", ".4s", ".8h", ".h",
6395 [(set (v4i32 V128:$dst),
6396 (Accum (v4i32 V128:$Rd),
6397 (v4i32 (int_arm64_neon_sqdmull
6398 (extract_high_v8i16 V128:$Rn),
6399 (extract_high_v8i16
6400 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6401 VectorIndexH:$idx))))))]> {
6402 bits<3> idx;
6403 let Inst{11} = idx{2};
6404 let Inst{21} = idx{1};
6405 let Inst{20} = idx{0};
6406 }
6407
6408 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6409 V128, V64,
6410 V128, VectorIndexS,
6411 asm, ".2d", ".2d", ".2s", ".s",
6412 [(set (v2i64 V128:$dst),
6413 (Accum (v2i64 V128:$Rd),
6414 (v2i64 (int_arm64_neon_sqdmull
6415 (v2i32 V64:$Rn),
6416 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6417 VectorIndexS:$idx))))))]> {
6418 bits<2> idx;
6419 let Inst{11} = idx{1};
6420 let Inst{21} = idx{0};
6421 }
6422
6423 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6424 V128, V128,
6425 V128, VectorIndexS,
6426 asm#"2", ".2d", ".2d", ".4s", ".s",
6427 [(set (v2i64 V128:$dst),
6428 (Accum (v2i64 V128:$Rd),
6429 (v2i64 (int_arm64_neon_sqdmull
6430 (extract_high_v4i32 V128:$Rn),
6431 (extract_high_v4i32
6432 (ARM64duplane32 (v4i32 V128:$Rm),
6433 VectorIndexS:$idx))))))]> {
6434 bits<2> idx;
6435 let Inst{11} = idx{1};
6436 let Inst{21} = idx{0};
6437 }
6438
6439 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6440 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6441 asm, ".h", "", "", ".h", []> {
6442 bits<3> idx;
6443 let Inst{11} = idx{2};
6444 let Inst{21} = idx{1};
6445 let Inst{20} = idx{0};
6446 }
6447
6448
6449 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6450 FPR64Op, FPR32Op, V128, VectorIndexS,
6451 asm, ".s", "", "", ".s",
6452 [(set (i64 FPR64Op:$dst),
6453 (Accum (i64 FPR64Op:$Rd),
6454 (i64 (int_arm64_neon_sqdmulls_scalar
6455 (i32 FPR32Op:$Rn),
6456 (i32 (vector_extract (v4i32 V128:$Rm),
6457 VectorIndexS:$idx))))))]> {
6458
6459 bits<2> idx;
6460 let Inst{11} = idx{1};
6461 let Inst{21} = idx{0};
6462 }
6463}
6464
6465multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6466 SDPatternOperator OpNode> {
6467 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6468 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6469 V128, V64,
6470 V128_lo, VectorIndexH,
6471 asm, ".4s", ".4s", ".4h", ".h",
6472 [(set (v4i32 V128:$Rd),
6473 (OpNode (v4i16 V64:$Rn),
6474 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6475 bits<3> idx;
6476 let Inst{11} = idx{2};
6477 let Inst{21} = idx{1};
6478 let Inst{20} = idx{0};
6479 }
6480
6481 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6482 V128, V128,
6483 V128_lo, VectorIndexH,
6484 asm#"2", ".4s", ".4s", ".8h", ".h",
6485 [(set (v4i32 V128:$Rd),
6486 (OpNode (extract_high_v8i16 V128:$Rn),
6487 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6488 VectorIndexH:$idx))))]> {
6489
6490 bits<3> idx;
6491 let Inst{11} = idx{2};
6492 let Inst{21} = idx{1};
6493 let Inst{20} = idx{0};
6494 }
6495
6496 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6497 V128, V64,
6498 V128, VectorIndexS,
6499 asm, ".2d", ".2d", ".2s", ".s",
6500 [(set (v2i64 V128:$Rd),
6501 (OpNode (v2i32 V64:$Rn),
6502 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6503 bits<2> idx;
6504 let Inst{11} = idx{1};
6505 let Inst{21} = idx{0};
6506 }
6507
6508 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6509 V128, V128,
6510 V128, VectorIndexS,
6511 asm#"2", ".2d", ".2d", ".4s", ".s",
6512 [(set (v2i64 V128:$Rd),
6513 (OpNode (extract_high_v4i32 V128:$Rn),
6514 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6515 VectorIndexS:$idx))))]> {
6516 bits<2> idx;
6517 let Inst{11} = idx{1};
6518 let Inst{21} = idx{0};
6519 }
6520 }
6521}
6522
6523multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6524 SDPatternOperator OpNode> {
6525 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6526 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6527 V128, V64,
6528 V128_lo, VectorIndexH,
6529 asm, ".4s", ".4s", ".4h", ".h",
6530 [(set (v4i32 V128:$dst),
6531 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6532 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6533 bits<3> idx;
6534 let Inst{11} = idx{2};
6535 let Inst{21} = idx{1};
6536 let Inst{20} = idx{0};
6537 }
6538
6539 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6540 V128, V128,
6541 V128_lo, VectorIndexH,
6542 asm#"2", ".4s", ".4s", ".8h", ".h",
6543 [(set (v4i32 V128:$dst),
6544 (OpNode (v4i32 V128:$Rd),
6545 (extract_high_v8i16 V128:$Rn),
6546 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6547 VectorIndexH:$idx))))]> {
6548 bits<3> idx;
6549 let Inst{11} = idx{2};
6550 let Inst{21} = idx{1};
6551 let Inst{20} = idx{0};
6552 }
6553
6554 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6555 V128, V64,
6556 V128, VectorIndexS,
6557 asm, ".2d", ".2d", ".2s", ".s",
6558 [(set (v2i64 V128:$dst),
6559 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6560 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6561 bits<2> idx;
6562 let Inst{11} = idx{1};
6563 let Inst{21} = idx{0};
6564 }
6565
6566 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6567 V128, V128,
6568 V128, VectorIndexS,
6569 asm#"2", ".2d", ".2d", ".4s", ".s",
6570 [(set (v2i64 V128:$dst),
6571 (OpNode (v2i64 V128:$Rd),
6572 (extract_high_v4i32 V128:$Rn),
6573 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6574 VectorIndexS:$idx))))]> {
6575 bits<2> idx;
6576 let Inst{11} = idx{1};
6577 let Inst{21} = idx{0};
6578 }
6579 }
6580}
6581
6582//----------------------------------------------------------------------------
6583// AdvSIMD scalar shift by immediate
6584//----------------------------------------------------------------------------
6585
6586let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6587class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6588 RegisterClass regtype1, RegisterClass regtype2,
6589 Operand immtype, string asm, list<dag> pattern>
6590 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6591 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6592 Sched<[WriteV]> {
6593 bits<5> Rd;
6594 bits<5> Rn;
6595 bits<7> imm;
6596 let Inst{31-30} = 0b01;
6597 let Inst{29} = U;
6598 let Inst{28-23} = 0b111110;
6599 let Inst{22-16} = fixed_imm;
6600 let Inst{15-11} = opc;
6601 let Inst{10} = 1;
6602 let Inst{9-5} = Rn;
6603 let Inst{4-0} = Rd;
6604}
6605
6606let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6607class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6608 RegisterClass regtype1, RegisterClass regtype2,
6609 Operand immtype, string asm, list<dag> pattern>
6610 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6611 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6612 Sched<[WriteV]> {
6613 bits<5> Rd;
6614 bits<5> Rn;
6615 bits<7> imm;
6616 let Inst{31-30} = 0b01;
6617 let Inst{29} = U;
6618 let Inst{28-23} = 0b111110;
6619 let Inst{22-16} = fixed_imm;
6620 let Inst{15-11} = opc;
6621 let Inst{10} = 1;
6622 let Inst{9-5} = Rn;
6623 let Inst{4-0} = Rd;
6624}
6625
6626
6627multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6628 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6629 FPR32, FPR32, vecshiftR32, asm, []> {
6630 let Inst{20-16} = imm{4-0};
6631 }
6632
6633 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6634 FPR64, FPR64, vecshiftR64, asm, []> {
6635 let Inst{21-16} = imm{5-0};
6636 }
6637}
6638
6639multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6640 SDPatternOperator OpNode> {
6641 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6642 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006643 [(set (i64 FPR64:$Rd),
6644 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006645 let Inst{21-16} = imm{5-0};
6646 }
Tim Northover5081cd02014-03-31 15:46:46 +00006647
6648 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6649 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006650}
6651
Tim Northover00ed9962014-03-29 10:18:08 +00006652multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6653 SDPatternOperator OpNode = null_frag> {
6654 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6655 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006656 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6657 (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006658 let Inst{21-16} = imm{5-0};
6659 }
Tim Northover5081cd02014-03-31 15:46:46 +00006660
6661 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6662 (i32 vecshiftR64:$imm))),
6663 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6664 vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006665}
6666
6667multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6668 SDPatternOperator OpNode> {
6669 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6670 FPR64, FPR64, vecshiftL64, asm,
6671 [(set (v1i64 FPR64:$Rd),
6672 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6673 let Inst{21-16} = imm{5-0};
6674 }
6675}
6676
6677let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6678multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6679 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6680 FPR64, FPR64, vecshiftL64, asm, []> {
6681 let Inst{21-16} = imm{5-0};
6682 }
6683}
6684
6685let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6686multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6687 SDPatternOperator OpNode = null_frag> {
6688 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6689 FPR8, FPR16, vecshiftR8, asm, []> {
6690 let Inst{18-16} = imm{2-0};
6691 }
6692
6693 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6694 FPR16, FPR32, vecshiftR16, asm, []> {
6695 let Inst{19-16} = imm{3-0};
6696 }
6697
6698 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6699 FPR32, FPR64, vecshiftR32, asm,
6700 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6701 let Inst{20-16} = imm{4-0};
6702 }
6703}
6704
6705multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6706 SDPatternOperator OpNode> {
6707 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6708 FPR8, FPR8, vecshiftL8, asm, []> {
6709 let Inst{18-16} = imm{2-0};
6710 }
6711
6712 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6713 FPR16, FPR16, vecshiftL16, asm, []> {
6714 let Inst{19-16} = imm{3-0};
6715 }
6716
6717 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6718 FPR32, FPR32, vecshiftL32, asm,
6719 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6720 let Inst{20-16} = imm{4-0};
6721 }
6722
6723 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6724 FPR64, FPR64, vecshiftL64, asm,
6725 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6726 (i32 vecshiftL64:$imm)))]> {
6727 let Inst{21-16} = imm{5-0};
6728 }
6729}
6730
6731multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6732 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6733 FPR8, FPR8, vecshiftR8, asm, []> {
6734 let Inst{18-16} = imm{2-0};
6735 }
6736
6737 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6738 FPR16, FPR16, vecshiftR16, asm, []> {
6739 let Inst{19-16} = imm{3-0};
6740 }
6741
6742 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6743 FPR32, FPR32, vecshiftR32, asm, []> {
6744 let Inst{20-16} = imm{4-0};
6745 }
6746
6747 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6748 FPR64, FPR64, vecshiftR64, asm, []> {
6749 let Inst{21-16} = imm{5-0};
6750 }
6751}
6752
6753//----------------------------------------------------------------------------
6754// AdvSIMD vector x indexed element
6755//----------------------------------------------------------------------------
6756
6757let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6758class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6759 RegisterOperand dst_reg, RegisterOperand src_reg,
6760 Operand immtype,
6761 string asm, string dst_kind, string src_kind,
6762 list<dag> pattern>
6763 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6764 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6765 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6766 Sched<[WriteV]> {
6767 bits<5> Rd;
6768 bits<5> Rn;
6769 let Inst{31} = 0;
6770 let Inst{30} = Q;
6771 let Inst{29} = U;
6772 let Inst{28-23} = 0b011110;
6773 let Inst{22-16} = fixed_imm;
6774 let Inst{15-11} = opc;
6775 let Inst{10} = 1;
6776 let Inst{9-5} = Rn;
6777 let Inst{4-0} = Rd;
6778}
6779
6780let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6781class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6782 RegisterOperand vectype1, RegisterOperand vectype2,
6783 Operand immtype,
6784 string asm, string dst_kind, string src_kind,
6785 list<dag> pattern>
6786 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6787 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6788 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6789 Sched<[WriteV]> {
6790 bits<5> Rd;
6791 bits<5> Rn;
6792 let Inst{31} = 0;
6793 let Inst{30} = Q;
6794 let Inst{29} = U;
6795 let Inst{28-23} = 0b011110;
6796 let Inst{22-16} = fixed_imm;
6797 let Inst{15-11} = opc;
6798 let Inst{10} = 1;
6799 let Inst{9-5} = Rn;
6800 let Inst{4-0} = Rd;
6801}
6802
6803multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6804 Intrinsic OpNode> {
6805 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6806 V64, V64, vecshiftR32,
6807 asm, ".2s", ".2s",
6808 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6809 bits<5> imm;
6810 let Inst{20-16} = imm;
6811 }
6812
6813 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6814 V128, V128, vecshiftR32,
6815 asm, ".4s", ".4s",
6816 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6817 bits<5> imm;
6818 let Inst{20-16} = imm;
6819 }
6820
6821 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6822 V128, V128, vecshiftR64,
6823 asm, ".2d", ".2d",
6824 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6825 bits<6> imm;
6826 let Inst{21-16} = imm;
6827 }
6828}
6829
6830multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6831 Intrinsic OpNode> {
6832 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6833 V64, V64, vecshiftR32,
6834 asm, ".2s", ".2s",
6835 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6836 bits<5> imm;
6837 let Inst{20-16} = imm;
6838 }
6839
6840 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6841 V128, V128, vecshiftR32,
6842 asm, ".4s", ".4s",
6843 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6844 bits<5> imm;
6845 let Inst{20-16} = imm;
6846 }
6847
6848 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6849 V128, V128, vecshiftR64,
6850 asm, ".2d", ".2d",
6851 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6852 bits<6> imm;
6853 let Inst{21-16} = imm;
6854 }
6855}
6856
6857multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6858 SDPatternOperator OpNode> {
6859 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6860 V64, V128, vecshiftR16Narrow,
6861 asm, ".8b", ".8h",
6862 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6863 bits<3> imm;
6864 let Inst{18-16} = imm;
6865 }
6866
6867 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6868 V128, V128, vecshiftR16Narrow,
6869 asm#"2", ".16b", ".8h", []> {
6870 bits<3> imm;
6871 let Inst{18-16} = imm;
6872 let hasSideEffects = 0;
6873 }
6874
6875 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6876 V64, V128, vecshiftR32Narrow,
6877 asm, ".4h", ".4s",
6878 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6879 bits<4> imm;
6880 let Inst{19-16} = imm;
6881 }
6882
6883 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6884 V128, V128, vecshiftR32Narrow,
6885 asm#"2", ".8h", ".4s", []> {
6886 bits<4> imm;
6887 let Inst{19-16} = imm;
6888 let hasSideEffects = 0;
6889 }
6890
6891 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6892 V64, V128, vecshiftR64Narrow,
6893 asm, ".2s", ".2d",
6894 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6895 bits<5> imm;
6896 let Inst{20-16} = imm;
6897 }
6898
6899 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6900 V128, V128, vecshiftR64Narrow,
6901 asm#"2", ".4s", ".2d", []> {
6902 bits<5> imm;
6903 let Inst{20-16} = imm;
6904 let hasSideEffects = 0;
6905 }
6906
6907 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
6908 // themselves, so put them here instead.
6909
6910 // Patterns involving what's effectively an insert high and a normal
6911 // intrinsic, represented by CONCAT_VECTORS.
6912 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
6913 vecshiftR16Narrow:$imm)),
6914 (!cast<Instruction>(NAME # "v16i8_shift")
6915 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6916 V128:$Rn, vecshiftR16Narrow:$imm)>;
6917 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
6918 vecshiftR32Narrow:$imm)),
6919 (!cast<Instruction>(NAME # "v8i16_shift")
6920 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6921 V128:$Rn, vecshiftR32Narrow:$imm)>;
6922 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
6923 vecshiftR64Narrow:$imm)),
6924 (!cast<Instruction>(NAME # "v4i32_shift")
6925 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6926 V128:$Rn, vecshiftR64Narrow:$imm)>;
6927}
6928
6929multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
6930 SDPatternOperator OpNode> {
6931 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6932 V64, V64, vecshiftL8,
6933 asm, ".8b", ".8b",
6934 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
6935 (i32 vecshiftL8:$imm)))]> {
6936 bits<3> imm;
6937 let Inst{18-16} = imm;
6938 }
6939
6940 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
6941 V128, V128, vecshiftL8,
6942 asm, ".16b", ".16b",
6943 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
6944 (i32 vecshiftL8:$imm)))]> {
6945 bits<3> imm;
6946 let Inst{18-16} = imm;
6947 }
6948
6949 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6950 V64, V64, vecshiftL16,
6951 asm, ".4h", ".4h",
6952 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
6953 (i32 vecshiftL16:$imm)))]> {
6954 bits<4> imm;
6955 let Inst{19-16} = imm;
6956 }
6957
6958 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
6959 V128, V128, vecshiftL16,
6960 asm, ".8h", ".8h",
6961 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6962 (i32 vecshiftL16:$imm)))]> {
6963 bits<4> imm;
6964 let Inst{19-16} = imm;
6965 }
6966
6967 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6968 V64, V64, vecshiftL32,
6969 asm, ".2s", ".2s",
6970 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
6971 (i32 vecshiftL32:$imm)))]> {
6972 bits<5> imm;
6973 let Inst{20-16} = imm;
6974 }
6975
6976 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6977 V128, V128, vecshiftL32,
6978 asm, ".4s", ".4s",
6979 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6980 (i32 vecshiftL32:$imm)))]> {
6981 bits<5> imm;
6982 let Inst{20-16} = imm;
6983 }
6984
6985 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6986 V128, V128, vecshiftL64,
6987 asm, ".2d", ".2d",
6988 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6989 (i32 vecshiftL64:$imm)))]> {
6990 bits<6> imm;
6991 let Inst{21-16} = imm;
6992 }
6993}
6994
6995multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
6996 SDPatternOperator OpNode> {
6997 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6998 V64, V64, vecshiftR8,
6999 asm, ".8b", ".8b",
7000 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7001 (i32 vecshiftR8:$imm)))]> {
7002 bits<3> imm;
7003 let Inst{18-16} = imm;
7004 }
7005
7006 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7007 V128, V128, vecshiftR8,
7008 asm, ".16b", ".16b",
7009 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7010 (i32 vecshiftR8:$imm)))]> {
7011 bits<3> imm;
7012 let Inst{18-16} = imm;
7013 }
7014
7015 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7016 V64, V64, vecshiftR16,
7017 asm, ".4h", ".4h",
7018 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7019 (i32 vecshiftR16:$imm)))]> {
7020 bits<4> imm;
7021 let Inst{19-16} = imm;
7022 }
7023
7024 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7025 V128, V128, vecshiftR16,
7026 asm, ".8h", ".8h",
7027 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7028 (i32 vecshiftR16:$imm)))]> {
7029 bits<4> imm;
7030 let Inst{19-16} = imm;
7031 }
7032
7033 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7034 V64, V64, vecshiftR32,
7035 asm, ".2s", ".2s",
7036 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7037 (i32 vecshiftR32:$imm)))]> {
7038 bits<5> imm;
7039 let Inst{20-16} = imm;
7040 }
7041
7042 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7043 V128, V128, vecshiftR32,
7044 asm, ".4s", ".4s",
7045 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7046 (i32 vecshiftR32:$imm)))]> {
7047 bits<5> imm;
7048 let Inst{20-16} = imm;
7049 }
7050
7051 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7052 V128, V128, vecshiftR64,
7053 asm, ".2d", ".2d",
7054 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7055 (i32 vecshiftR64:$imm)))]> {
7056 bits<6> imm;
7057 let Inst{21-16} = imm;
7058 }
7059}
7060
7061let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7062multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7063 SDPatternOperator OpNode = null_frag> {
7064 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7065 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7066 [(set (v8i8 V64:$dst),
7067 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7068 (i32 vecshiftR8:$imm)))]> {
7069 bits<3> imm;
7070 let Inst{18-16} = imm;
7071 }
7072
7073 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7074 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7075 [(set (v16i8 V128:$dst),
7076 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7077 (i32 vecshiftR8:$imm)))]> {
7078 bits<3> imm;
7079 let Inst{18-16} = imm;
7080 }
7081
7082 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7083 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7084 [(set (v4i16 V64:$dst),
7085 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7086 (i32 vecshiftR16:$imm)))]> {
7087 bits<4> imm;
7088 let Inst{19-16} = imm;
7089 }
7090
7091 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7092 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7093 [(set (v8i16 V128:$dst),
7094 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7095 (i32 vecshiftR16:$imm)))]> {
7096 bits<4> imm;
7097 let Inst{19-16} = imm;
7098 }
7099
7100 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7101 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7102 [(set (v2i32 V64:$dst),
7103 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7104 (i32 vecshiftR32:$imm)))]> {
7105 bits<5> imm;
7106 let Inst{20-16} = imm;
7107 }
7108
7109 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7110 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7111 [(set (v4i32 V128:$dst),
7112 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7113 (i32 vecshiftR32:$imm)))]> {
7114 bits<5> imm;
7115 let Inst{20-16} = imm;
7116 }
7117
7118 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7119 V128, V128, vecshiftR64,
7120 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7121 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7122 (i32 vecshiftR64:$imm)))]> {
7123 bits<6> imm;
7124 let Inst{21-16} = imm;
7125 }
7126}
7127
7128multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7129 SDPatternOperator OpNode = null_frag> {
7130 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7131 V64, V64, vecshiftL8,
7132 asm, ".8b", ".8b",
7133 [(set (v8i8 V64:$dst),
7134 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7135 (i32 vecshiftL8:$imm)))]> {
7136 bits<3> imm;
7137 let Inst{18-16} = imm;
7138 }
7139
7140 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7141 V128, V128, vecshiftL8,
7142 asm, ".16b", ".16b",
7143 [(set (v16i8 V128:$dst),
7144 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7145 (i32 vecshiftL8:$imm)))]> {
7146 bits<3> imm;
7147 let Inst{18-16} = imm;
7148 }
7149
7150 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7151 V64, V64, vecshiftL16,
7152 asm, ".4h", ".4h",
7153 [(set (v4i16 V64:$dst),
7154 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7155 (i32 vecshiftL16:$imm)))]> {
7156 bits<4> imm;
7157 let Inst{19-16} = imm;
7158 }
7159
7160 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7161 V128, V128, vecshiftL16,
7162 asm, ".8h", ".8h",
7163 [(set (v8i16 V128:$dst),
7164 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7165 (i32 vecshiftL16:$imm)))]> {
7166 bits<4> imm;
7167 let Inst{19-16} = imm;
7168 }
7169
7170 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7171 V64, V64, vecshiftL32,
7172 asm, ".2s", ".2s",
7173 [(set (v2i32 V64:$dst),
7174 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7175 (i32 vecshiftL32:$imm)))]> {
7176 bits<5> imm;
7177 let Inst{20-16} = imm;
7178 }
7179
7180 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7181 V128, V128, vecshiftL32,
7182 asm, ".4s", ".4s",
7183 [(set (v4i32 V128:$dst),
7184 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7185 (i32 vecshiftL32:$imm)))]> {
7186 bits<5> imm;
7187 let Inst{20-16} = imm;
7188 }
7189
7190 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7191 V128, V128, vecshiftL64,
7192 asm, ".2d", ".2d",
7193 [(set (v2i64 V128:$dst),
7194 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7195 (i32 vecshiftL64:$imm)))]> {
7196 bits<6> imm;
7197 let Inst{21-16} = imm;
7198 }
7199}
7200
7201multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7202 SDPatternOperator OpNode> {
7203 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7204 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7205 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7206 bits<3> imm;
7207 let Inst{18-16} = imm;
7208 }
7209
7210 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7211 V128, V128, vecshiftL8,
7212 asm#"2", ".8h", ".16b",
7213 [(set (v8i16 V128:$Rd),
7214 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7215 bits<3> imm;
7216 let Inst{18-16} = imm;
7217 }
7218
7219 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7220 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7221 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7222 bits<4> imm;
7223 let Inst{19-16} = imm;
7224 }
7225
7226 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7227 V128, V128, vecshiftL16,
7228 asm#"2", ".4s", ".8h",
7229 [(set (v4i32 V128:$Rd),
7230 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7231
7232 bits<4> imm;
7233 let Inst{19-16} = imm;
7234 }
7235
7236 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7237 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7238 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7239 bits<5> imm;
7240 let Inst{20-16} = imm;
7241 }
7242
7243 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7244 V128, V128, vecshiftL32,
7245 asm#"2", ".2d", ".4s",
7246 [(set (v2i64 V128:$Rd),
7247 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7248 bits<5> imm;
7249 let Inst{20-16} = imm;
7250 }
7251}
7252
7253
7254//---
7255// Vector load/store
7256//---
7257// SIMD ldX/stX no-index memory references don't allow the optional
7258// ", #0" constant and handle post-indexing explicitly, so we use
7259// a more specialized parse method for them. Otherwise, it's the same as
7260// the general am_noindex handling.
7261def MemorySIMDNoIndexOperand : AsmOperandClass {
7262 let Name = "MemorySIMDNoIndex";
7263 let ParserMethod = "tryParseNoIndexMemory";
7264}
7265def am_simdnoindex : Operand<i64>,
7266 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7267 let PrintMethod = "printAMNoIndex";
7268 let ParserMatchClass = MemorySIMDNoIndexOperand;
7269 let MIOperandInfo = (ops GPR64sp:$base);
7270 let DecoderMethod = "DecodeGPR64spRegisterClass";
7271}
7272
7273class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7274 string asm, dag oops, dag iops, list<dag> pattern>
7275 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7276 bits<5> Vt;
7277 bits<5> vaddr;
7278 let Inst{31} = 0;
7279 let Inst{30} = Q;
7280 let Inst{29-23} = 0b0011000;
7281 let Inst{22} = L;
7282 let Inst{21-16} = 0b000000;
7283 let Inst{15-12} = opcode;
7284 let Inst{11-10} = size;
7285 let Inst{9-5} = vaddr;
7286 let Inst{4-0} = Vt;
7287}
7288
7289class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7290 string asm, dag oops, dag iops>
7291 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7292 bits<5> Vt;
7293 bits<5> vaddr;
7294 bits<5> Xm;
7295 let Inst{31} = 0;
7296 let Inst{30} = Q;
7297 let Inst{29-23} = 0b0011001;
7298 let Inst{22} = L;
7299 let Inst{21} = 0;
7300 let Inst{20-16} = Xm;
7301 let Inst{15-12} = opcode;
7302 let Inst{11-10} = size;
7303 let Inst{9-5} = vaddr;
7304 let Inst{4-0} = Vt;
7305 let DecoderMethod = "DecodeSIMDLdStPost";
7306}
7307
7308// The immediate form of AdvSIMD post-indexed addressing is encoded with
7309// register post-index addressing from the zero register.
7310multiclass SIMDLdStAliases<string asm, string layout, string Count,
7311 int Offset, int Size> {
7312 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7313 // "ld1\t$Vt, $vaddr, #16"
7314 // may get mapped to
7315 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7316 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7317 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7318 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7319 am_simdnoindex:$vaddr, XZR), 1>;
7320
7321 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7322 // "ld1.8b\t$Vt, $vaddr, #16"
7323 // may get mapped to
7324 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7325 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7326 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7327 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7328 am_simdnoindex:$vaddr, XZR), 0>;
7329
7330 // E.g. "ld1.8b { v0, v1 }, [x1]"
7331 // "ld1\t$Vt, $vaddr"
7332 // may get mapped to
7333 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7334 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7335 (!cast<Instruction>(NAME # Count # "v" # layout)
7336 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7337 am_simdnoindex:$vaddr), 0>;
7338
7339 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7340 // "ld1\t$Vt, $vaddr, $Xm"
7341 // may get mapped to
7342 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7343 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7344 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7345 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7346 am_simdnoindex:$vaddr,
7347 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7348}
7349
7350multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7351 int Offset64, bits<4> opcode> {
7352 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7353 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7354 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7355 (ins am_simdnoindex:$vaddr), []>;
7356 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7357 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7358 (ins am_simdnoindex:$vaddr), []>;
7359 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7360 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7361 (ins am_simdnoindex:$vaddr), []>;
7362 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7363 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7364 (ins am_simdnoindex:$vaddr), []>;
7365 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7366 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7367 (ins am_simdnoindex:$vaddr), []>;
7368 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7369 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7370 (ins am_simdnoindex:$vaddr), []>;
7371 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7372 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7373 (ins am_simdnoindex:$vaddr), []>;
7374
7375
7376 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7377 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7378 (ins am_simdnoindex:$vaddr,
7379 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7380 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7381 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7382 (ins am_simdnoindex:$vaddr,
7383 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7384 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7385 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7386 (ins am_simdnoindex:$vaddr,
7387 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7388 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7389 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7390 (ins am_simdnoindex:$vaddr,
7391 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7392 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7393 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7394 (ins am_simdnoindex:$vaddr,
7395 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7396 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7397 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7398 (ins am_simdnoindex:$vaddr,
7399 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7400 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7401 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7402 (ins am_simdnoindex:$vaddr,
7403 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7404 }
7405
7406 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7407 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7408 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7409 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7410 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7411 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7412 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7413}
7414
7415// Only ld1/st1 has a v1d version.
7416multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7417 int Offset64, bits<4> opcode> {
7418 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7419 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7420 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7421 am_simdnoindex:$vaddr), []>;
7422 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7423 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7424 am_simdnoindex:$vaddr), []>;
7425 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7426 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7427 am_simdnoindex:$vaddr), []>;
7428 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7429 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7430 am_simdnoindex:$vaddr), []>;
7431 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7432 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7433 am_simdnoindex:$vaddr), []>;
7434 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7435 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7436 am_simdnoindex:$vaddr), []>;
7437 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7438 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7439 am_simdnoindex:$vaddr), []>;
7440
7441 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7442 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7443 am_simdnoindex:$vaddr,
7444 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7445 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7446 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7447 am_simdnoindex:$vaddr,
7448 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7449 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7450 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7451 am_simdnoindex:$vaddr,
7452 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7453 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7454 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7455 am_simdnoindex:$vaddr,
7456 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7457 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7458 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7459 am_simdnoindex:$vaddr,
7460 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7461 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7462 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7463 am_simdnoindex:$vaddr,
7464 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7465 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7466 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7467 am_simdnoindex:$vaddr,
7468 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7469 }
7470
7471 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7472 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7473 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7474 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7475 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7476 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7477 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7478}
7479
7480multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7481 int Offset128, int Offset64, bits<4> opcode>
7482 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7483
7484 // LD1 instructions have extra "1d" variants.
7485 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7486 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7487 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7488 (ins am_simdnoindex:$vaddr), []>;
7489
7490 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7491 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7492 (ins am_simdnoindex:$vaddr,
7493 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7494 }
7495
7496 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7497}
7498
7499multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7500 int Offset128, int Offset64, bits<4> opcode>
7501 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7502
7503 // ST1 instructions have extra "1d" variants.
7504 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7505 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7506 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7507 am_simdnoindex:$vaddr), []>;
7508
7509 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7510 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7511 am_simdnoindex:$vaddr,
7512 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7513 }
7514
7515 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7516}
7517
7518multiclass SIMDLd1Multiple<string asm> {
7519 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7520 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7521 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7522 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7523}
7524
7525multiclass SIMDSt1Multiple<string asm> {
7526 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7527 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7528 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7529 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7530}
7531
7532multiclass SIMDLd2Multiple<string asm> {
7533 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7534}
7535
7536multiclass SIMDSt2Multiple<string asm> {
7537 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7538}
7539
7540multiclass SIMDLd3Multiple<string asm> {
7541 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7542}
7543
7544multiclass SIMDSt3Multiple<string asm> {
7545 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7546}
7547
7548multiclass SIMDLd4Multiple<string asm> {
7549 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7550}
7551
7552multiclass SIMDSt4Multiple<string asm> {
7553 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7554}
7555
7556//---
7557// AdvSIMD Load/store single-element
7558//---
7559
7560class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7561 string asm, string operands, dag oops, dag iops,
7562 list<dag> pattern>
7563 : I<oops, iops, asm, operands, "", pattern> {
7564 bits<5> Vt;
7565 bits<5> vaddr;
7566 let Inst{31} = 0;
7567 let Inst{29-24} = 0b001101;
7568 let Inst{22} = L;
7569 let Inst{21} = R;
7570 let Inst{15-13} = opcode;
7571 let Inst{9-5} = vaddr;
7572 let Inst{4-0} = Vt;
7573 let DecoderMethod = "DecodeSIMDLdStSingle";
7574}
7575
7576class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7577 string asm, string operands, dag oops, dag iops,
7578 list<dag> pattern>
7579 : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7580 bits<5> Vt;
7581 bits<5> vaddr;
7582 let Inst{31} = 0;
7583 let Inst{29-24} = 0b001101;
7584 let Inst{22} = L;
7585 let Inst{21} = R;
7586 let Inst{15-13} = opcode;
7587 let Inst{9-5} = vaddr;
7588 let Inst{4-0} = Vt;
7589 let DecoderMethod = "DecodeSIMDLdStSingleTied";
7590}
7591
7592
7593let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7594class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7595 Operand listtype>
7596 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7597 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7598 let Inst{30} = Q;
7599 let Inst{23} = 0;
7600 let Inst{20-16} = 0b00000;
7601 let Inst{12} = S;
7602 let Inst{11-10} = size;
7603}
7604let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7605class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7606 string asm, Operand listtype, Operand GPR64pi>
7607 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7608 (outs listtype:$Vt),
7609 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7610 bits<5> Xm;
7611 let Inst{30} = Q;
7612 let Inst{23} = 1;
7613 let Inst{20-16} = Xm;
7614 let Inst{12} = S;
7615 let Inst{11-10} = size;
7616}
7617
7618multiclass SIMDLdrAliases<string asm, string layout, string Count,
7619 int Offset, int Size> {
7620 // E.g. "ld1r { v0.8b }, [x1], #1"
7621 // "ld1r.8b\t$Vt, $vaddr, #1"
7622 // may get mapped to
7623 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7624 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7625 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7626 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7627 am_simdnoindex:$vaddr, XZR), 1>;
7628
7629 // E.g. "ld1r.8b { v0 }, [x1], #1"
7630 // "ld1r.8b\t$Vt, $vaddr, #1"
7631 // may get mapped to
7632 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7633 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7634 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7635 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7636 am_simdnoindex:$vaddr, XZR), 0>;
7637
7638 // E.g. "ld1r.8b { v0 }, [x1]"
7639 // "ld1r.8b\t$Vt, $vaddr"
7640 // may get mapped to
7641 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7642 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7643 (!cast<Instruction>(NAME # "v" # layout)
7644 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7645 am_simdnoindex:$vaddr), 0>;
7646
7647 // E.g. "ld1r.8b { v0 }, [x1], x2"
7648 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7649 // may get mapped to
7650 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7651 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7652 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7653 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7654 am_simdnoindex:$vaddr,
7655 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7656}
7657
7658multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7659 int Offset1, int Offset2, int Offset4, int Offset8> {
7660 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7661 !cast<Operand>("VecList" # Count # "8b")>;
7662 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7663 !cast<Operand>("VecList" # Count #"16b")>;
7664 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7665 !cast<Operand>("VecList" # Count #"4h")>;
7666 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7667 !cast<Operand>("VecList" # Count #"8h")>;
7668 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7669 !cast<Operand>("VecList" # Count #"2s")>;
7670 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7671 !cast<Operand>("VecList" # Count #"4s")>;
7672 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7673 !cast<Operand>("VecList" # Count #"1d")>;
7674 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7675 !cast<Operand>("VecList" # Count #"2d")>;
7676
7677 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7678 !cast<Operand>("VecList" # Count # "8b"),
7679 !cast<Operand>("GPR64pi" # Offset1)>;
7680 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7681 !cast<Operand>("VecList" # Count # "16b"),
7682 !cast<Operand>("GPR64pi" # Offset1)>;
7683 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7684 !cast<Operand>("VecList" # Count # "4h"),
7685 !cast<Operand>("GPR64pi" # Offset2)>;
7686 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7687 !cast<Operand>("VecList" # Count # "8h"),
7688 !cast<Operand>("GPR64pi" # Offset2)>;
7689 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7690 !cast<Operand>("VecList" # Count # "2s"),
7691 !cast<Operand>("GPR64pi" # Offset4)>;
7692 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7693 !cast<Operand>("VecList" # Count # "4s"),
7694 !cast<Operand>("GPR64pi" # Offset4)>;
7695 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7696 !cast<Operand>("VecList" # Count # "1d"),
7697 !cast<Operand>("GPR64pi" # Offset8)>;
7698 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7699 !cast<Operand>("VecList" # Count # "2d"),
7700 !cast<Operand>("GPR64pi" # Offset8)>;
7701
7702 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7703 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7704 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7705 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7706 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7707 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7708 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7709 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7710}
7711
7712class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7713 dag oops, dag iops, list<dag> pattern>
7714 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7715 pattern> {
7716 // idx encoded in Q:S:size fields.
7717 bits<4> idx;
7718 let Inst{30} = idx{3};
7719 let Inst{23} = 0;
7720 let Inst{20-16} = 0b00000;
7721 let Inst{12} = idx{2};
7722 let Inst{11-10} = idx{1-0};
7723}
7724class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7725 dag oops, dag iops, list<dag> pattern>
7726 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7727 pattern> {
7728 // idx encoded in Q:S:size fields.
7729 bits<4> idx;
7730 let Inst{30} = idx{3};
7731 let Inst{23} = 0;
7732 let Inst{20-16} = 0b00000;
7733 let Inst{12} = idx{2};
7734 let Inst{11-10} = idx{1-0};
7735}
7736class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7737 dag oops, dag iops>
7738 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7739 oops, iops, []> {
7740 // idx encoded in Q:S:size fields.
7741 bits<4> idx;
7742 bits<5> Xm;
7743 let Inst{30} = idx{3};
7744 let Inst{23} = 1;
7745 let Inst{20-16} = Xm;
7746 let Inst{12} = idx{2};
7747 let Inst{11-10} = idx{1-0};
7748}
7749class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7750 dag oops, dag iops>
7751 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7752 oops, iops, []> {
7753 // idx encoded in Q:S:size fields.
7754 bits<4> idx;
7755 bits<5> Xm;
7756 let Inst{30} = idx{3};
7757 let Inst{23} = 1;
7758 let Inst{20-16} = Xm;
7759 let Inst{12} = idx{2};
7760 let Inst{11-10} = idx{1-0};
7761}
7762
7763class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7764 dag oops, dag iops, list<dag> pattern>
7765 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7766 pattern> {
7767 // idx encoded in Q:S:size<1> fields.
7768 bits<3> idx;
7769 let Inst{30} = idx{2};
7770 let Inst{23} = 0;
7771 let Inst{20-16} = 0b00000;
7772 let Inst{12} = idx{1};
7773 let Inst{11} = idx{0};
7774 let Inst{10} = size;
7775}
7776class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7777 dag oops, dag iops, list<dag> pattern>
7778 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7779 pattern> {
7780 // idx encoded in Q:S:size<1> fields.
7781 bits<3> idx;
7782 let Inst{30} = idx{2};
7783 let Inst{23} = 0;
7784 let Inst{20-16} = 0b00000;
7785 let Inst{12} = idx{1};
7786 let Inst{11} = idx{0};
7787 let Inst{10} = size;
7788}
7789
7790class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7791 dag oops, dag iops>
7792 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7793 oops, iops, []> {
7794 // idx encoded in Q:S:size<1> fields.
7795 bits<3> idx;
7796 bits<5> Xm;
7797 let Inst{30} = idx{2};
7798 let Inst{23} = 1;
7799 let Inst{20-16} = Xm;
7800 let Inst{12} = idx{1};
7801 let Inst{11} = idx{0};
7802 let Inst{10} = size;
7803}
7804class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7805 dag oops, dag iops>
7806 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7807 oops, iops, []> {
7808 // idx encoded in Q:S:size<1> fields.
7809 bits<3> idx;
7810 bits<5> Xm;
7811 let Inst{30} = idx{2};
7812 let Inst{23} = 1;
7813 let Inst{20-16} = Xm;
7814 let Inst{12} = idx{1};
7815 let Inst{11} = idx{0};
7816 let Inst{10} = size;
7817}
7818class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7819 dag oops, dag iops, list<dag> pattern>
7820 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7821 pattern> {
7822 // idx encoded in Q:S fields.
7823 bits<2> idx;
7824 let Inst{30} = idx{1};
7825 let Inst{23} = 0;
7826 let Inst{20-16} = 0b00000;
7827 let Inst{12} = idx{0};
7828 let Inst{11-10} = size;
7829}
7830class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7831 dag oops, dag iops, list<dag> pattern>
7832 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7833 pattern> {
7834 // idx encoded in Q:S fields.
7835 bits<2> idx;
7836 let Inst{30} = idx{1};
7837 let Inst{23} = 0;
7838 let Inst{20-16} = 0b00000;
7839 let Inst{12} = idx{0};
7840 let Inst{11-10} = size;
7841}
7842class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7843 string asm, dag oops, dag iops>
7844 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7845 oops, iops, []> {
7846 // idx encoded in Q:S fields.
7847 bits<2> idx;
7848 bits<5> Xm;
7849 let Inst{30} = idx{1};
7850 let Inst{23} = 1;
7851 let Inst{20-16} = Xm;
7852 let Inst{12} = idx{0};
7853 let Inst{11-10} = size;
7854}
7855class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7856 string asm, dag oops, dag iops>
7857 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7858 oops, iops, []> {
7859 // idx encoded in Q:S fields.
7860 bits<2> idx;
7861 bits<5> Xm;
7862 let Inst{30} = idx{1};
7863 let Inst{23} = 1;
7864 let Inst{20-16} = Xm;
7865 let Inst{12} = idx{0};
7866 let Inst{11-10} = size;
7867}
7868class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7869 dag oops, dag iops, list<dag> pattern>
7870 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7871 pattern> {
7872 // idx encoded in Q field.
7873 bits<1> idx;
7874 let Inst{30} = idx;
7875 let Inst{23} = 0;
7876 let Inst{20-16} = 0b00000;
7877 let Inst{12} = 0;
7878 let Inst{11-10} = size;
7879}
7880class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7881 dag oops, dag iops, list<dag> pattern>
7882 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7883 pattern> {
7884 // idx encoded in Q field.
7885 bits<1> idx;
7886 let Inst{30} = idx;
7887 let Inst{23} = 0;
7888 let Inst{20-16} = 0b00000;
7889 let Inst{12} = 0;
7890 let Inst{11-10} = size;
7891}
7892class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7893 string asm, dag oops, dag iops>
7894 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7895 oops, iops, []> {
7896 // idx encoded in Q field.
7897 bits<1> idx;
7898 bits<5> Xm;
7899 let Inst{30} = idx;
7900 let Inst{23} = 1;
7901 let Inst{20-16} = Xm;
7902 let Inst{12} = 0;
7903 let Inst{11-10} = size;
7904}
7905class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7906 string asm, dag oops, dag iops>
7907 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7908 oops, iops, []> {
7909 // idx encoded in Q field.
7910 bits<1> idx;
7911 bits<5> Xm;
7912 let Inst{30} = idx;
7913 let Inst{23} = 1;
7914 let Inst{20-16} = Xm;
7915 let Inst{12} = 0;
7916 let Inst{11-10} = size;
7917}
7918
7919let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7920multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
7921 RegisterOperand listtype,
7922 RegisterOperand GPR64pi> {
7923 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
7924 (outs listtype:$dst),
7925 (ins listtype:$Vt, VectorIndexB:$idx,
7926 am_simdnoindex:$vaddr), []>;
7927
7928 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
7929 (outs listtype:$dst),
7930 (ins listtype:$Vt, VectorIndexB:$idx,
7931 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7932}
7933let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7934multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
7935 RegisterOperand listtype,
7936 RegisterOperand GPR64pi> {
7937 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
7938 (outs listtype:$dst),
7939 (ins listtype:$Vt, VectorIndexH:$idx,
7940 am_simdnoindex:$vaddr), []>;
7941
7942 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
7943 (outs listtype:$dst),
7944 (ins listtype:$Vt, VectorIndexH:$idx,
7945 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7946}
7947let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7948multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
7949 RegisterOperand listtype,
7950 RegisterOperand GPR64pi> {
7951 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
7952 (outs listtype:$dst),
7953 (ins listtype:$Vt, VectorIndexS:$idx,
7954 am_simdnoindex:$vaddr), []>;
7955
7956 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
7957 (outs listtype:$dst),
7958 (ins listtype:$Vt, VectorIndexS:$idx,
7959 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7960}
7961let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7962multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00007963 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00007964 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
7965 (outs listtype:$dst),
7966 (ins listtype:$Vt, VectorIndexD:$idx,
7967 am_simdnoindex:$vaddr), []>;
7968
7969 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
7970 (outs listtype:$dst),
7971 (ins listtype:$Vt, VectorIndexD:$idx,
7972 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7973}
7974let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
7975multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00007976 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00007977 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
7978 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00007979 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00007980
7981 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
7982 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
7983 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7984}
7985let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
7986multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00007987 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00007988 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
7989 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00007990 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00007991
7992 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
7993 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
7994 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7995}
7996let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
7997multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00007998 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00007999 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8000 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008001 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008002
8003 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8004 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8005 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8006}
8007let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8008multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008009 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008010 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8011 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008012 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008013
8014 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8015 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8016 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8017}
8018
8019multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8020 string Count, int Offset, Operand idxtype> {
8021 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8022 // "ld1\t$Vt, $vaddr, #1"
8023 // may get mapped to
8024 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8025 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8026 (!cast<Instruction>(NAME # Type # "_POST")
8027 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8028 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8029
8030 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8031 // "ld1.8b\t$Vt, $vaddr, #1"
8032 // may get mapped to
8033 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8034 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8035 (!cast<Instruction>(NAME # Type # "_POST")
8036 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8037 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8038
8039 // E.g. "ld1.8b { v0 }[0], [x1]"
8040 // "ld1.8b\t$Vt, $vaddr"
8041 // may get mapped to
8042 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8043 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8044 (!cast<Instruction>(NAME # Type)
8045 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8046 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8047
8048 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8049 // "ld1.8b\t$Vt, $vaddr, $Xm"
8050 // may get mapped to
8051 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8052 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8053 (!cast<Instruction>(NAME # Type # "_POST")
8054 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8055 idxtype:$idx, am_simdnoindex:$vaddr,
8056 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8057}
8058
8059multiclass SIMDLdSt1SingleAliases<string asm> {
8060 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8061 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8062 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8063 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8064}
8065
8066multiclass SIMDLdSt2SingleAliases<string asm> {
8067 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8068 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8069 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8070 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8071}
8072
8073multiclass SIMDLdSt3SingleAliases<string asm> {
8074 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8075 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8076 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8077 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8078}
8079
8080multiclass SIMDLdSt4SingleAliases<string asm> {
8081 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8082 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8083 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8084 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8085}
8086
8087//----------------------------------------------------------------------------
8088// Crypto extensions
8089//----------------------------------------------------------------------------
8090
8091let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8092class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8093 list<dag> pat>
8094 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8095 Sched<[WriteV]>{
8096 bits<5> Rd;
8097 bits<5> Rn;
8098 let Inst{31-16} = 0b0100111000101000;
8099 let Inst{15-12} = opc;
8100 let Inst{11-10} = 0b10;
8101 let Inst{9-5} = Rn;
8102 let Inst{4-0} = Rd;
8103}
8104
8105class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8106 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8107 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8108
8109class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8110 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8111 "$Rd = $dst",
8112 [(set (v16i8 V128:$dst),
8113 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8114
8115let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8116class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8117 dag oops, dag iops, list<dag> pat>
8118 : I<oops, iops, asm,
8119 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8120 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8121 Sched<[WriteV]>{
8122 bits<5> Rd;
8123 bits<5> Rn;
8124 bits<5> Rm;
8125 let Inst{31-21} = 0b01011110000;
8126 let Inst{20-16} = Rm;
8127 let Inst{15} = 0;
8128 let Inst{14-12} = opc;
8129 let Inst{11-10} = 0b00;
8130 let Inst{9-5} = Rn;
8131 let Inst{4-0} = Rd;
8132}
8133
8134class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8135 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8136 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8137 [(set (v4i32 FPR128:$dst),
8138 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8139 (v4i32 V128:$Rm)))]>;
8140
8141class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8142 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8143 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8144 [(set (v4i32 V128:$dst),
8145 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8146 (v4i32 V128:$Rm)))]>;
8147
8148class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8149 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8150 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8151 [(set (v4i32 FPR128:$dst),
8152 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8153 (v4i32 V128:$Rm)))]>;
8154
8155let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8156class SHA2OpInst<bits<4> opc, string asm, string kind,
8157 string cstr, dag oops, dag iops,
8158 list<dag> pat>
8159 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8160 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8161 Sched<[WriteV]>{
8162 bits<5> Rd;
8163 bits<5> Rn;
8164 let Inst{31-16} = 0b0101111000101000;
8165 let Inst{15-12} = opc;
8166 let Inst{11-10} = 0b10;
8167 let Inst{9-5} = Rn;
8168 let Inst{4-0} = Rd;
8169}
8170
8171class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8172 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8173 (ins V128:$Rd, V128:$Rn),
8174 [(set (v4i32 V128:$dst),
8175 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8176
8177class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8178 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8179 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8180
8181// Allow the size specifier tokens to be upper case, not just lower.
8182def : TokenAlias<".8B", ".8b">;
8183def : TokenAlias<".4H", ".4h">;
8184def : TokenAlias<".2S", ".2s">;
8185def : TokenAlias<".1D", ".1d">;
8186def : TokenAlias<".16B", ".16b">;
8187def : TokenAlias<".8H", ".8h">;
8188def : TokenAlias<".4S", ".4s">;
8189def : TokenAlias<".2D", ".2d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008190def : TokenAlias<".1Q", ".1q">;
Tim Northover00ed9962014-03-29 10:18:08 +00008191def : TokenAlias<".B", ".b">;
8192def : TokenAlias<".H", ".h">;
8193def : TokenAlias<".S", ".s">;
8194def : TokenAlias<".D", ".d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008195def : TokenAlias<".Q", ".q">;