1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
11 // Describe AArch64 instructions format here
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
17 class Format<bits<2> val> {
21 def PseudoFrm : Format<0>;
22 def NormalFrm : Format<1>; // Do we need any others?
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26 field bits<32> Inst; // Instruction encoding.
27 // Mask of bits that cause an encoding to be UNPREDICTABLE.
28 // If a bit is set, then if the corresponding bit in the
29 // target encoding differs from its value in the "Inst" field,
30 // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
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 = "AArch64";
37 bits<2> Form = F.Value;
39 let Constraints = cstr;
42 // Pseudo instructions (don't have encoding information)
43 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44 : AArch64Inst<PseudoFrm, cstr> {
45 dag OutOperandList = oops;
46 dag InOperandList = iops;
47 let Pattern = pattern;
48 let isCodeGenOnly = 1;
51 // Real instructions (have encoding information)
52 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
53 let Pattern = pattern;
57 // Normal instructions
58 class I<dag oops, dag iops, string asm, string operands, string cstr,
60 : EncodedI<cstr, pattern> {
61 dag OutOperandList = oops;
62 dag InOperandList = iops;
63 let AsmString = !strconcat(asm, operands);
66 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68 class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
70 // Helper fragment for an extract of the high portion of a 128-bit vector.
71 def extract_high_v16i8 :
72 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73 def extract_high_v8i16 :
74 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75 def extract_high_v4i32 :
76 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77 def extract_high_v2i64 :
78 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
80 //===----------------------------------------------------------------------===//
81 // Asm Operand Classes.
84 // Shifter operand for arithmetic shifted encodings.
85 def ShifterOperand : AsmOperandClass {
89 // Shifter operand for mov immediate encodings.
90 def MovImm32ShifterOperand : AsmOperandClass {
91 let SuperClasses = [ShifterOperand];
92 let Name = "MovImm32Shifter";
93 let RenderMethod = "addShifterOperands";
94 let DiagnosticType = "InvalidMovImm32Shift";
96 def MovImm64ShifterOperand : AsmOperandClass {
97 let SuperClasses = [ShifterOperand];
98 let Name = "MovImm64Shifter";
99 let RenderMethod = "addShifterOperands";
100 let DiagnosticType = "InvalidMovImm64Shift";
103 // Shifter operand for arithmetic register shifted encodings.
104 class ArithmeticShifterOperand<int width> : AsmOperandClass {
105 let SuperClasses = [ShifterOperand];
106 let Name = "ArithmeticShifter" # width;
107 let PredicateMethod = "isArithmeticShifter<" # width # ">";
108 let RenderMethod = "addShifterOperands";
109 let DiagnosticType = "AddSubRegShift" # width;
112 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
113 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
115 // Shifter operand for logical register shifted encodings.
116 class LogicalShifterOperand<int width> : AsmOperandClass {
117 let SuperClasses = [ShifterOperand];
118 let Name = "LogicalShifter" # width;
119 let PredicateMethod = "isLogicalShifter<" # width # ">";
120 let RenderMethod = "addShifterOperands";
121 let DiagnosticType = "AddSubRegShift" # width;
124 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
125 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
127 // Shifter operand for logical vector 128/64-bit shifted encodings.
128 def LogicalVecShifterOperand : AsmOperandClass {
129 let SuperClasses = [ShifterOperand];
130 let Name = "LogicalVecShifter";
131 let RenderMethod = "addShifterOperands";
133 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
134 let SuperClasses = [LogicalVecShifterOperand];
135 let Name = "LogicalVecHalfWordShifter";
136 let RenderMethod = "addShifterOperands";
139 // The "MSL" shifter on the vector MOVI instruction.
140 def MoveVecShifterOperand : AsmOperandClass {
141 let SuperClasses = [ShifterOperand];
142 let Name = "MoveVecShifter";
143 let RenderMethod = "addShifterOperands";
146 // Extend operand for arithmetic encodings.
147 def ExtendOperand : AsmOperandClass {
149 let DiagnosticType = "AddSubRegExtendLarge";
151 def ExtendOperand64 : AsmOperandClass {
152 let SuperClasses = [ExtendOperand];
153 let Name = "Extend64";
154 let DiagnosticType = "AddSubRegExtendSmall";
156 // 'extend' that's a lsl of a 64-bit register.
157 def ExtendOperandLSL64 : AsmOperandClass {
158 let SuperClasses = [ExtendOperand];
159 let Name = "ExtendLSL64";
160 let RenderMethod = "addExtend64Operands";
161 let DiagnosticType = "AddSubRegExtendLarge";
164 // 8-bit floating-point immediate encodings.
165 def FPImmOperand : AsmOperandClass {
167 let ParserMethod = "tryParseFPImm";
168 let DiagnosticType = "InvalidFPImm";
171 def CondCode : AsmOperandClass {
172 let Name = "CondCode";
173 let DiagnosticType = "InvalidCondCode";
176 // A 32-bit register pasrsed as 64-bit
177 def GPR32as64Operand : AsmOperandClass {
178 let Name = "GPR32as64";
180 def GPR32as64 : RegisterOperand<GPR32> {
181 let ParserMatchClass = GPR32as64Operand;
184 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
185 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
186 // are encoded as the eight bit value 'abcdefgh'.
187 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
190 //===----------------------------------------------------------------------===//
191 // Operand Definitions.
194 // ADR[P] instruction labels.
195 def AdrpOperand : AsmOperandClass {
196 let Name = "AdrpLabel";
197 let ParserMethod = "tryParseAdrpLabel";
198 let DiagnosticType = "InvalidLabel";
200 def adrplabel : Operand<i64> {
201 let EncoderMethod = "getAdrLabelOpValue";
202 let PrintMethod = "printAdrpLabel";
203 let ParserMatchClass = AdrpOperand;
206 def AdrOperand : AsmOperandClass {
207 let Name = "AdrLabel";
208 let ParserMethod = "tryParseAdrLabel";
209 let DiagnosticType = "InvalidLabel";
211 def adrlabel : Operand<i64> {
212 let EncoderMethod = "getAdrLabelOpValue";
213 let ParserMatchClass = AdrOperand;
216 // simm9 predicate - True if the immediate is in the range [-256, 255].
217 def SImm9Operand : AsmOperandClass {
219 let DiagnosticType = "InvalidMemoryIndexedSImm9";
221 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
222 let ParserMatchClass = SImm9Operand;
225 // simm7sN predicate - True if the immediate is a multiple of N in the range
226 // [-64 * N, 63 * N].
227 class SImm7Scaled<int Scale> : AsmOperandClass {
228 let Name = "SImm7s" # Scale;
229 let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7";
232 def SImm7s4Operand : SImm7Scaled<4>;
233 def SImm7s8Operand : SImm7Scaled<8>;
234 def SImm7s16Operand : SImm7Scaled<16>;
236 def simm7s4 : Operand<i32> {
237 let ParserMatchClass = SImm7s4Operand;
238 let PrintMethod = "printImmScale<4>";
241 def simm7s8 : Operand<i32> {
242 let ParserMatchClass = SImm7s8Operand;
243 let PrintMethod = "printImmScale<8>";
246 def simm7s16 : Operand<i32> {
247 let ParserMatchClass = SImm7s16Operand;
248 let PrintMethod = "printImmScale<16>";
251 def am_indexed7s8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
252 def am_indexed7s16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
253 def am_indexed7s32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
254 def am_indexed7s64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
255 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
257 class AsmImmRange<int Low, int High> : AsmOperandClass {
258 let Name = "Imm" # Low # "_" # High;
259 let DiagnosticType = "InvalidImm" # Low # "_" # High;
262 def Imm1_8Operand : AsmImmRange<1, 8>;
263 def Imm1_16Operand : AsmImmRange<1, 16>;
264 def Imm1_32Operand : AsmImmRange<1, 32>;
265 def Imm1_64Operand : AsmImmRange<1, 64>;
267 def MovZSymbolG3AsmOperand : AsmOperandClass {
268 let Name = "MovZSymbolG3";
269 let RenderMethod = "addImmOperands";
272 def movz_symbol_g3 : Operand<i32> {
273 let ParserMatchClass = MovZSymbolG3AsmOperand;
276 def MovZSymbolG2AsmOperand : AsmOperandClass {
277 let Name = "MovZSymbolG2";
278 let RenderMethod = "addImmOperands";
281 def movz_symbol_g2 : Operand<i32> {
282 let ParserMatchClass = MovZSymbolG2AsmOperand;
285 def MovZSymbolG1AsmOperand : AsmOperandClass {
286 let Name = "MovZSymbolG1";
287 let RenderMethod = "addImmOperands";
290 def movz_symbol_g1 : Operand<i32> {
291 let ParserMatchClass = MovZSymbolG1AsmOperand;
294 def MovZSymbolG0AsmOperand : AsmOperandClass {
295 let Name = "MovZSymbolG0";
296 let RenderMethod = "addImmOperands";
299 def movz_symbol_g0 : Operand<i32> {
300 let ParserMatchClass = MovZSymbolG0AsmOperand;
303 def MovKSymbolG3AsmOperand : AsmOperandClass {
304 let Name = "MovKSymbolG3";
305 let RenderMethod = "addImmOperands";
308 def movk_symbol_g3 : Operand<i32> {
309 let ParserMatchClass = MovKSymbolG3AsmOperand;
312 def MovKSymbolG2AsmOperand : AsmOperandClass {
313 let Name = "MovKSymbolG2";
314 let RenderMethod = "addImmOperands";
317 def movk_symbol_g2 : Operand<i32> {
318 let ParserMatchClass = MovKSymbolG2AsmOperand;
321 def MovKSymbolG1AsmOperand : AsmOperandClass {
322 let Name = "MovKSymbolG1";
323 let RenderMethod = "addImmOperands";
326 def movk_symbol_g1 : Operand<i32> {
327 let ParserMatchClass = MovKSymbolG1AsmOperand;
330 def MovKSymbolG0AsmOperand : AsmOperandClass {
331 let Name = "MovKSymbolG0";
332 let RenderMethod = "addImmOperands";
335 def movk_symbol_g0 : Operand<i32> {
336 let ParserMatchClass = MovKSymbolG0AsmOperand;
339 class fixedpoint_i32<ValueType FloatVT>
341 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
342 let EncoderMethod = "getFixedPointScaleOpValue";
343 let DecoderMethod = "DecodeFixedPointScaleImm32";
344 let ParserMatchClass = Imm1_32Operand;
347 class fixedpoint_i64<ValueType FloatVT>
349 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
350 let EncoderMethod = "getFixedPointScaleOpValue";
351 let DecoderMethod = "DecodeFixedPointScaleImm64";
352 let ParserMatchClass = Imm1_64Operand;
355 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
356 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
357 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
359 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
360 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
361 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
363 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
364 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
366 let EncoderMethod = "getVecShiftR8OpValue";
367 let DecoderMethod = "DecodeVecShiftR8Imm";
368 let ParserMatchClass = Imm1_8Operand;
370 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
371 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
373 let EncoderMethod = "getVecShiftR16OpValue";
374 let DecoderMethod = "DecodeVecShiftR16Imm";
375 let ParserMatchClass = Imm1_16Operand;
377 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
378 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
380 let EncoderMethod = "getVecShiftR16OpValue";
381 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
382 let ParserMatchClass = Imm1_8Operand;
384 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
385 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
387 let EncoderMethod = "getVecShiftR32OpValue";
388 let DecoderMethod = "DecodeVecShiftR32Imm";
389 let ParserMatchClass = Imm1_32Operand;
391 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
392 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
394 let EncoderMethod = "getVecShiftR32OpValue";
395 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
396 let ParserMatchClass = Imm1_16Operand;
398 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
399 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
401 let EncoderMethod = "getVecShiftR64OpValue";
402 let DecoderMethod = "DecodeVecShiftR64Imm";
403 let ParserMatchClass = Imm1_64Operand;
405 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
406 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
408 let EncoderMethod = "getVecShiftR64OpValue";
409 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
410 let ParserMatchClass = Imm1_32Operand;
413 def Imm0_1Operand : AsmImmRange<0, 1>;
414 def Imm0_7Operand : AsmImmRange<0, 7>;
415 def Imm0_15Operand : AsmImmRange<0, 15>;
416 def Imm0_31Operand : AsmImmRange<0, 31>;
417 def Imm0_63Operand : AsmImmRange<0, 63>;
419 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
420 return (((uint32_t)Imm) < 8);
422 let EncoderMethod = "getVecShiftL8OpValue";
423 let DecoderMethod = "DecodeVecShiftL8Imm";
424 let ParserMatchClass = Imm0_7Operand;
426 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
427 return (((uint32_t)Imm) < 16);
429 let EncoderMethod = "getVecShiftL16OpValue";
430 let DecoderMethod = "DecodeVecShiftL16Imm";
431 let ParserMatchClass = Imm0_15Operand;
433 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
434 return (((uint32_t)Imm) < 32);
436 let EncoderMethod = "getVecShiftL32OpValue";
437 let DecoderMethod = "DecodeVecShiftL32Imm";
438 let ParserMatchClass = Imm0_31Operand;
440 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
441 return (((uint32_t)Imm) < 64);
443 let EncoderMethod = "getVecShiftL64OpValue";
444 let DecoderMethod = "DecodeVecShiftL64Imm";
445 let ParserMatchClass = Imm0_63Operand;
449 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
450 // instructions for splatting repeating bit patterns across the immediate.
451 def logical_imm32_XFORM : SDNodeXForm<imm, [{
452 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
453 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
455 def logical_imm64_XFORM : SDNodeXForm<imm, [{
456 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
457 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
460 let DiagnosticType = "LogicalSecondSource" in {
461 def LogicalImm32Operand : AsmOperandClass {
462 let Name = "LogicalImm32";
464 def LogicalImm64Operand : AsmOperandClass {
465 let Name = "LogicalImm64";
467 def LogicalImm32NotOperand : AsmOperandClass {
468 let Name = "LogicalImm32Not";
470 def LogicalImm64NotOperand : AsmOperandClass {
471 let Name = "LogicalImm64Not";
474 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
475 return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
476 }], logical_imm32_XFORM> {
477 let PrintMethod = "printLogicalImm32";
478 let ParserMatchClass = LogicalImm32Operand;
480 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
481 return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
482 }], logical_imm64_XFORM> {
483 let PrintMethod = "printLogicalImm64";
484 let ParserMatchClass = LogicalImm64Operand;
486 def logical_imm32_not : Operand<i32> {
487 let ParserMatchClass = LogicalImm32NotOperand;
489 def logical_imm64_not : Operand<i64> {
490 let ParserMatchClass = LogicalImm64NotOperand;
493 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
494 def Imm0_65535Operand : AsmImmRange<0, 65535>;
495 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
496 return ((uint32_t)Imm) < 65536;
498 let ParserMatchClass = Imm0_65535Operand;
499 let PrintMethod = "printHexImm";
502 // imm0_255 predicate - True if the immediate is in the range [0,255].
503 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
504 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
505 return ((uint32_t)Imm) < 256;
507 let ParserMatchClass = Imm0_255Operand;
508 let PrintMethod = "printHexImm";
511 // imm0_127 predicate - True if the immediate is in the range [0,127]
512 def Imm0_127Operand : AsmImmRange<0, 127>;
513 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
514 return ((uint32_t)Imm) < 128;
516 let ParserMatchClass = Imm0_127Operand;
517 let PrintMethod = "printHexImm";
520 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
521 // for all shift-amounts.
523 // imm0_63 predicate - True if the immediate is in the range [0,63]
524 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
525 return ((uint64_t)Imm) < 64;
527 let ParserMatchClass = Imm0_63Operand;
530 // imm0_31 predicate - True if the immediate is in the range [0,31]
531 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
532 return ((uint64_t)Imm) < 32;
534 let ParserMatchClass = Imm0_31Operand;
537 // True if the 32-bit immediate is in the range [0,31]
538 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
539 return ((uint64_t)Imm) < 32;
541 let ParserMatchClass = Imm0_31Operand;
544 // imm0_1 predicate - True if the immediate is in the range [0,1]
545 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
546 return ((uint64_t)Imm) < 2;
548 let ParserMatchClass = Imm0_1Operand;
551 // imm0_15 predicate - True if the immediate is in the range [0,15]
552 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
553 return ((uint64_t)Imm) < 16;
555 let ParserMatchClass = Imm0_15Operand;
558 // imm0_7 predicate - True if the immediate is in the range [0,7]
559 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
560 return ((uint64_t)Imm) < 8;
562 let ParserMatchClass = Imm0_7Operand;
565 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
566 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
567 return ((uint32_t)Imm) < 16;
569 let ParserMatchClass = Imm0_15Operand;
572 // An arithmetic shifter operand:
573 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
575 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
576 let PrintMethod = "printShifter";
577 let ParserMatchClass = !cast<AsmOperandClass>(
578 "ArithmeticShifterOperand" # width);
581 def arith_shift32 : arith_shift<i32, 32>;
582 def arith_shift64 : arith_shift<i64, 64>;
584 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
586 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
587 let PrintMethod = "printShiftedRegister";
588 let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
591 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
592 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
594 // An arithmetic shifter operand:
595 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
597 class logical_shift<int width> : Operand<i32> {
598 let PrintMethod = "printShifter";
599 let ParserMatchClass = !cast<AsmOperandClass>(
600 "LogicalShifterOperand" # width);
603 def logical_shift32 : logical_shift<32>;
604 def logical_shift64 : logical_shift<64>;
606 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
608 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
609 let PrintMethod = "printShiftedRegister";
610 let MIOperandInfo = (ops regclass, shiftop);
613 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
614 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
616 // A logical vector shifter operand:
617 // {7-6} - shift type: 00 = lsl
618 // {5-0} - imm6: #0, #8, #16, or #24
619 def logical_vec_shift : Operand<i32> {
620 let PrintMethod = "printShifter";
621 let EncoderMethod = "getVecShifterOpValue";
622 let ParserMatchClass = LogicalVecShifterOperand;
625 // A logical vector half-word shifter operand:
626 // {7-6} - shift type: 00 = lsl
627 // {5-0} - imm6: #0 or #8
628 def logical_vec_hw_shift : Operand<i32> {
629 let PrintMethod = "printShifter";
630 let EncoderMethod = "getVecShifterOpValue";
631 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
634 // A vector move shifter operand:
635 // {0} - imm1: #8 or #16
636 def move_vec_shift : Operand<i32> {
637 let PrintMethod = "printShifter";
638 let EncoderMethod = "getMoveVecShifterOpValue";
639 let ParserMatchClass = MoveVecShifterOperand;
642 let DiagnosticType = "AddSubSecondSource" in {
643 def AddSubImmOperand : AsmOperandClass {
644 let Name = "AddSubImm";
645 let ParserMethod = "tryParseAddSubImm";
647 def AddSubImmNegOperand : AsmOperandClass {
648 let Name = "AddSubImmNeg";
649 let ParserMethod = "tryParseAddSubImm";
652 // An ADD/SUB immediate shifter operand:
654 // {7-6} - shift type: 00 = lsl
655 // {5-0} - imm6: #0 or #12
656 class addsub_shifted_imm<ValueType Ty>
657 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
658 let PrintMethod = "printAddSubImm";
659 let EncoderMethod = "getAddSubImmOpValue";
660 let ParserMatchClass = AddSubImmOperand;
661 let MIOperandInfo = (ops i32imm, i32imm);
664 class addsub_shifted_imm_neg<ValueType Ty>
666 let EncoderMethod = "getAddSubImmOpValue";
667 let ParserMatchClass = AddSubImmNegOperand;
668 let MIOperandInfo = (ops i32imm, i32imm);
671 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
672 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
673 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
674 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
676 class neg_addsub_shifted_imm<ValueType Ty>
677 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
678 let PrintMethod = "printAddSubImm";
679 let EncoderMethod = "getAddSubImmOpValue";
680 let ParserMatchClass = AddSubImmOperand;
681 let MIOperandInfo = (ops i32imm, i32imm);
684 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
685 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
687 // An extend operand:
688 // {5-3} - extend type
690 def arith_extend : Operand<i32> {
691 let PrintMethod = "printArithExtend";
692 let ParserMatchClass = ExtendOperand;
694 def arith_extend64 : Operand<i32> {
695 let PrintMethod = "printArithExtend";
696 let ParserMatchClass = ExtendOperand64;
699 // 'extend' that's a lsl of a 64-bit register.
700 def arith_extendlsl64 : Operand<i32> {
701 let PrintMethod = "printArithExtend";
702 let ParserMatchClass = ExtendOperandLSL64;
705 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
706 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
707 let PrintMethod = "printExtendedRegister";
708 let MIOperandInfo = (ops GPR32, arith_extend);
711 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
712 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
713 let PrintMethod = "printExtendedRegister";
714 let MIOperandInfo = (ops GPR32, arith_extend64);
717 // Floating-point immediate.
718 def fpimm16 : Operand<f16>,
719 PatLeaf<(f16 fpimm), [{
720 return AArch64_AM::getFP16Imm(N->getValueAPF()) != -1;
721 }], SDNodeXForm<fpimm, [{
722 APFloat InVal = N->getValueAPF();
723 uint32_t enc = AArch64_AM::getFP16Imm(InVal);
724 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
726 let ParserMatchClass = FPImmOperand;
727 let PrintMethod = "printFPImmOperand";
729 def fpimm32 : Operand<f32>,
730 PatLeaf<(f32 fpimm), [{
731 return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
732 }], SDNodeXForm<fpimm, [{
733 APFloat InVal = N->getValueAPF();
734 uint32_t enc = AArch64_AM::getFP32Imm(InVal);
735 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
737 let ParserMatchClass = FPImmOperand;
738 let PrintMethod = "printFPImmOperand";
740 def fpimm64 : Operand<f64>,
741 PatLeaf<(f64 fpimm), [{
742 return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
743 }], SDNodeXForm<fpimm, [{
744 APFloat InVal = N->getValueAPF();
745 uint32_t enc = AArch64_AM::getFP64Imm(InVal);
746 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
748 let ParserMatchClass = FPImmOperand;
749 let PrintMethod = "printFPImmOperand";
752 def fpimm8 : Operand<i32> {
753 let ParserMatchClass = FPImmOperand;
754 let PrintMethod = "printFPImmOperand";
757 def fpimm0 : PatLeaf<(fpimm), [{
758 return N->isExactlyValue(+0.0);
761 // Vector lane operands
762 class AsmVectorIndex<string Suffix> : AsmOperandClass {
763 let Name = "VectorIndex" # Suffix;
764 let DiagnosticType = "InvalidIndex" # Suffix;
766 def VectorIndex1Operand : AsmVectorIndex<"1">;
767 def VectorIndexBOperand : AsmVectorIndex<"B">;
768 def VectorIndexHOperand : AsmVectorIndex<"H">;
769 def VectorIndexSOperand : AsmVectorIndex<"S">;
770 def VectorIndexDOperand : AsmVectorIndex<"D">;
772 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
773 return ((uint64_t)Imm) == 1;
775 let ParserMatchClass = VectorIndex1Operand;
776 let PrintMethod = "printVectorIndex";
777 let MIOperandInfo = (ops i64imm);
779 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
780 return ((uint64_t)Imm) < 16;
782 let ParserMatchClass = VectorIndexBOperand;
783 let PrintMethod = "printVectorIndex";
784 let MIOperandInfo = (ops i64imm);
786 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
787 return ((uint64_t)Imm) < 8;
789 let ParserMatchClass = VectorIndexHOperand;
790 let PrintMethod = "printVectorIndex";
791 let MIOperandInfo = (ops i64imm);
793 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
794 return ((uint64_t)Imm) < 4;
796 let ParserMatchClass = VectorIndexSOperand;
797 let PrintMethod = "printVectorIndex";
798 let MIOperandInfo = (ops i64imm);
800 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
801 return ((uint64_t)Imm) < 2;
803 let ParserMatchClass = VectorIndexDOperand;
804 let PrintMethod = "printVectorIndex";
805 let MIOperandInfo = (ops i64imm);
808 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
809 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
810 // are encoded as the eight bit value 'abcdefgh'.
811 def simdimmtype10 : Operand<i32>,
812 PatLeaf<(f64 fpimm), [{
813 return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
816 }], SDNodeXForm<fpimm, [{
817 APFloat InVal = N->getValueAPF();
818 uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
821 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
823 let ParserMatchClass = SIMDImmType10Operand;
824 let PrintMethod = "printSIMDType10Operand";
832 // Base encoding for system instruction operands.
833 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
834 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
835 list<dag> pattern = []>
836 : I<oops, iops, asm, operands, "", pattern> {
837 let Inst{31-22} = 0b1101010100;
841 // System instructions which do not have an Rt register.
842 class SimpleSystemI<bit L, dag iops, string asm, string operands,
843 list<dag> pattern = []>
844 : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
845 let Inst{4-0} = 0b11111;
848 // System instructions which have an Rt register.
849 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
850 : BaseSystemI<L, oops, iops, asm, operands>,
856 // Hint instructions that take both a CRm and a 3-bit immediate.
857 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
858 // model patterns with sufficiently fine granularity
859 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
860 class HintI<string mnemonic>
861 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
862 [(int_aarch64_hint imm0_127:$imm)]>,
865 let Inst{20-12} = 0b000110010;
866 let Inst{11-5} = imm;
869 // System instructions taking a single literal operand which encodes into
870 // CRm. op2 differentiates the opcodes.
871 def BarrierAsmOperand : AsmOperandClass {
872 let Name = "Barrier";
873 let ParserMethod = "tryParseBarrierOperand";
875 def barrier_op : Operand<i32> {
876 let PrintMethod = "printBarrierOption";
877 let ParserMatchClass = BarrierAsmOperand;
879 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
880 list<dag> pattern = []>
881 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
882 Sched<[WriteBarrier]> {
884 let Inst{20-12} = 0b000110011;
885 let Inst{11-8} = CRm;
889 // MRS/MSR system instructions. These have different operand classes because
890 // a different subset of registers can be accessed through each instruction.
891 def MRSSystemRegisterOperand : AsmOperandClass {
892 let Name = "MRSSystemRegister";
893 let ParserMethod = "tryParseSysReg";
894 let DiagnosticType = "MRS";
896 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
897 def mrs_sysreg_op : Operand<i32> {
898 let ParserMatchClass = MRSSystemRegisterOperand;
899 let DecoderMethod = "DecodeMRSSystemRegister";
900 let PrintMethod = "printMRSSystemRegister";
903 def MSRSystemRegisterOperand : AsmOperandClass {
904 let Name = "MSRSystemRegister";
905 let ParserMethod = "tryParseSysReg";
906 let DiagnosticType = "MSR";
908 def msr_sysreg_op : Operand<i32> {
909 let ParserMatchClass = MSRSystemRegisterOperand;
910 let DecoderMethod = "DecodeMSRSystemRegister";
911 let PrintMethod = "printMSRSystemRegister";
914 def PSBHintOperand : AsmOperandClass {
915 let Name = "PSBHint";
916 let ParserMethod = "tryParsePSBHint";
918 def psbhint_op : Operand<i32> {
919 let ParserMatchClass = PSBHintOperand;
920 let PrintMethod = "printPSBHintOp";
921 let MCOperandPredicate = [{
922 // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
923 // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
927 (void)AArch64PSBHint::PSBHintMapper().toString(MCOp.getImm(),
928 STI.getFeatureBits(), ValidNamed);
933 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
934 "mrs", "\t$Rt, $systemreg"> {
936 let Inst{20-5} = systemreg;
939 // FIXME: Some of these def NZCV, others don't. Best way to model that?
940 // Explicitly modeling each of the system register as a register class
941 // would do it, but feels like overkill at this point.
942 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
943 "msr", "\t$systemreg, $Rt"> {
945 let Inst{20-5} = systemreg;
948 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
949 let Name = "SystemPStateFieldWithImm0_15";
950 let ParserMethod = "tryParseSysReg";
952 def pstatefield4_op : Operand<i32> {
953 let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
954 let PrintMethod = "printSystemPStateField";
958 class MSRpstateImm0_15
959 : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
960 "msr", "\t$pstatefield, $imm">,
964 let Inst{20-19} = 0b00;
965 let Inst{18-16} = pstatefield{5-3};
966 let Inst{15-12} = 0b0100;
967 let Inst{11-8} = imm;
968 let Inst{7-5} = pstatefield{2-0};
970 let DecoderMethod = "DecodeSystemPStateInstruction";
971 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
972 // Fail the decoder should attempt to decode the instruction as MSRI.
973 let hasCompleteDecoder = 0;
976 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
977 let Name = "SystemPStateFieldWithImm0_1";
978 let ParserMethod = "tryParseSysReg";
980 def pstatefield1_op : Operand<i32> {
981 let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
982 let PrintMethod = "printSystemPStateField";
986 class MSRpstateImm0_1
987 : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
988 "msr", "\t$pstatefield, $imm">,
992 let Inst{20-19} = 0b00;
993 let Inst{18-16} = pstatefield{5-3};
994 let Inst{15-9} = 0b0100000;
996 let Inst{7-5} = pstatefield{2-0};
998 let DecoderMethod = "DecodeSystemPStateInstruction";
999 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1000 // Fail the decoder should attempt to decode the instruction as MSRI.
1001 let hasCompleteDecoder = 0;
1004 // SYS and SYSL generic system instructions.
1005 def SysCRAsmOperand : AsmOperandClass {
1007 let ParserMethod = "tryParseSysCROperand";
1010 def sys_cr_op : Operand<i32> {
1011 let PrintMethod = "printSysCROperand";
1012 let ParserMatchClass = SysCRAsmOperand;
1015 class SystemXtI<bit L, string asm>
1016 : RtSystemI<L, (outs),
1017 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1018 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1023 let Inst{20-19} = 0b01;
1024 let Inst{18-16} = op1;
1025 let Inst{15-12} = Cn;
1026 let Inst{11-8} = Cm;
1027 let Inst{7-5} = op2;
1030 class SystemLXtI<bit L, string asm>
1031 : RtSystemI<L, (outs),
1032 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1033 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1038 let Inst{20-19} = 0b01;
1039 let Inst{18-16} = op1;
1040 let Inst{15-12} = Cn;
1041 let Inst{11-8} = Cm;
1042 let Inst{7-5} = op2;
1046 // Branch (register) instructions:
1054 // otherwise UNDEFINED
1055 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1056 string operands, list<dag> pattern>
1057 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1058 let Inst{31-25} = 0b1101011;
1059 let Inst{24-21} = opc;
1060 let Inst{20-16} = 0b11111;
1061 let Inst{15-10} = 0b000000;
1062 let Inst{4-0} = 0b00000;
1065 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1066 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1071 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1072 class SpecialReturn<bits<4> opc, string asm>
1073 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1074 let Inst{9-5} = 0b11111;
1078 // Conditional branch instruction.
1082 // 4-bit immediate. Pretty-printed as <cc>
1083 def ccode : Operand<i32> {
1084 let PrintMethod = "printCondCode";
1085 let ParserMatchClass = CondCode;
1087 def inv_ccode : Operand<i32> {
1088 // AL and NV are invalid in the aliases which use inv_ccode
1089 let PrintMethod = "printInverseCondCode";
1090 let ParserMatchClass = CondCode;
1091 let MCOperandPredicate = [{
1092 return MCOp.isImm() &&
1093 MCOp.getImm() != AArch64CC::AL &&
1094 MCOp.getImm() != AArch64CC::NV;
1098 // Conditional branch target. 19-bit immediate. The low two bits of the target
1099 // offset are implied zero and so are not part of the immediate.
1100 def PCRelLabel19Operand : AsmOperandClass {
1101 let Name = "PCRelLabel19";
1102 let DiagnosticType = "InvalidLabel";
1104 def am_brcond : Operand<OtherVT> {
1105 let EncoderMethod = "getCondBranchTargetOpValue";
1106 let DecoderMethod = "DecodePCRelLabel19";
1107 let PrintMethod = "printAlignedLabel";
1108 let ParserMatchClass = PCRelLabel19Operand;
1111 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1112 "b", ".$cond\t$target", "",
1113 [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1116 let isTerminator = 1;
1121 let Inst{31-24} = 0b01010100;
1122 let Inst{23-5} = target;
1124 let Inst{3-0} = cond;
1128 // Compare-and-branch instructions.
1130 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1131 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1132 asm, "\t$Rt, $target", "",
1133 [(node regtype:$Rt, bb:$target)]>,
1136 let isTerminator = 1;
1140 let Inst{30-25} = 0b011010;
1142 let Inst{23-5} = target;
1146 multiclass CmpBranch<bit op, string asm, SDNode node> {
1147 def W : BaseCmpBranch<GPR32, op, asm, node> {
1150 def X : BaseCmpBranch<GPR64, op, asm, node> {
1156 // Test-bit-and-branch instructions.
1158 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1159 // the target offset are implied zero and so are not part of the immediate.
1160 def BranchTarget14Operand : AsmOperandClass {
1161 let Name = "BranchTarget14";
1163 def am_tbrcond : Operand<OtherVT> {
1164 let EncoderMethod = "getTestBranchTargetOpValue";
1165 let PrintMethod = "printAlignedLabel";
1166 let ParserMatchClass = BranchTarget14Operand;
1169 // AsmOperand classes to emit (or not) special diagnostics
1170 def TBZImm0_31Operand : AsmOperandClass {
1171 let Name = "TBZImm0_31";
1172 let PredicateMethod = "isImm0_31";
1173 let RenderMethod = "addImm0_31Operands";
1175 def TBZImm32_63Operand : AsmOperandClass {
1176 let Name = "Imm32_63";
1177 let DiagnosticType = "InvalidImm0_63";
1180 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1181 return (((uint32_t)Imm) < 32);
1183 let ParserMatchClass = matcher;
1186 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1187 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1189 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1190 return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1192 let ParserMatchClass = TBZImm32_63Operand;
1195 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1196 bit op, string asm, SDNode node>
1197 : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1198 asm, "\t$Rt, $bit_off, $target", "",
1199 [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1202 let isTerminator = 1;
1208 let Inst{30-25} = 0b011011;
1210 let Inst{23-19} = bit_off{4-0};
1211 let Inst{18-5} = target;
1214 let DecoderMethod = "DecodeTestAndBranch";
1217 multiclass TestBranch<bit op, string asm, SDNode node> {
1218 def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1222 def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1226 // Alias X-reg with 0-31 imm to W-Reg.
1227 def : InstAlias<asm # "\t$Rd, $imm, $target",
1228 (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1229 tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1230 def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1231 (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1232 tbz_imm0_31_diag:$imm, bb:$target)>;
1236 // Unconditional branch (immediate) instructions.
1238 def BranchTarget26Operand : AsmOperandClass {
1239 let Name = "BranchTarget26";
1240 let DiagnosticType = "InvalidLabel";
1242 def am_b_target : Operand<OtherVT> {
1243 let EncoderMethod = "getBranchTargetOpValue";
1244 let PrintMethod = "printAlignedLabel";
1245 let ParserMatchClass = BranchTarget26Operand;
1247 def am_bl_target : Operand<i64> {
1248 let EncoderMethod = "getBranchTargetOpValue";
1249 let PrintMethod = "printAlignedLabel";
1250 let ParserMatchClass = BranchTarget26Operand;
1253 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1254 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1257 let Inst{30-26} = 0b00101;
1258 let Inst{25-0} = addr;
1260 let DecoderMethod = "DecodeUnconditionalBranch";
1263 class BranchImm<bit op, string asm, list<dag> pattern>
1264 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1265 class CallImm<bit op, string asm, list<dag> pattern>
1266 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1269 // Basic one-operand data processing instructions.
1272 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1273 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1274 SDPatternOperator node>
1275 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1276 [(set regtype:$Rd, (node regtype:$Rn))]>,
1277 Sched<[WriteI, ReadI]> {
1281 let Inst{30-13} = 0b101101011000000000;
1282 let Inst{12-10} = opc;
1287 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1288 multiclass OneOperandData<bits<3> opc, string asm,
1289 SDPatternOperator node = null_frag> {
1290 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1294 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1299 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1300 : BaseOneOperandData<opc, GPR32, asm, node> {
1304 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1305 : BaseOneOperandData<opc, GPR64, asm, node> {
1310 // Basic two-operand data processing instructions.
1312 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1314 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1315 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1316 Sched<[WriteI, ReadI, ReadI]> {
1321 let Inst{30} = isSub;
1322 let Inst{28-21} = 0b11010000;
1323 let Inst{20-16} = Rm;
1324 let Inst{15-10} = 0;
1329 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1331 : BaseBaseAddSubCarry<isSub, regtype, asm,
1332 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1334 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1336 : BaseBaseAddSubCarry<isSub, regtype, asm,
1337 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1342 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1343 SDNode OpNode, SDNode OpNode_setflags> {
1344 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1348 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1354 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1359 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1366 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1367 SDPatternOperator OpNode>
1368 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1369 asm, "\t$Rd, $Rn, $Rm", "",
1370 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1374 let Inst{30-21} = 0b0011010110;
1375 let Inst{20-16} = Rm;
1376 let Inst{15-14} = 0b00;
1377 let Inst{13-10} = opc;
1382 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1383 SDPatternOperator OpNode>
1384 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1385 let Inst{10} = isSigned;
1388 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1389 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1390 Sched<[WriteID32, ReadID, ReadID]> {
1393 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1394 Sched<[WriteID64, ReadID, ReadID]> {
1399 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1400 SDPatternOperator OpNode = null_frag>
1401 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1402 Sched<[WriteIS, ReadI]> {
1403 let Inst{11-10} = shift_type;
1406 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1407 def Wr : BaseShift<shift_type, GPR32, asm> {
1411 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1415 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1416 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1417 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1419 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1420 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1422 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1423 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1425 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1426 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1429 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1430 : InstAlias<asm#"\t$dst, $src1, $src2",
1431 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1433 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1434 RegisterClass addtype, string asm,
1436 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1437 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1442 let Inst{30-24} = 0b0011011;
1443 let Inst{23-21} = opc;
1444 let Inst{20-16} = Rm;
1445 let Inst{15} = isSub;
1446 let Inst{14-10} = Ra;
1451 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1452 // MADD/MSUB generation is decided by MachineCombiner.cpp
1453 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1454 [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1455 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1459 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1460 [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1461 Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1466 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1467 SDNode AccNode, SDNode ExtNode>
1468 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1469 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1470 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1471 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1475 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1476 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1477 asm, "\t$Rd, $Rn, $Rm", "",
1478 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1479 Sched<[WriteIM64, ReadIM, ReadIM]> {
1483 let Inst{31-24} = 0b10011011;
1484 let Inst{23-21} = opc;
1485 let Inst{20-16} = Rm;
1490 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1491 // (i.e. all bits 1) but is ignored by the processor.
1492 let PostEncoderMethod = "fixMulHigh";
1495 class MulAccumWAlias<string asm, Instruction inst>
1496 : InstAlias<asm#"\t$dst, $src1, $src2",
1497 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1498 class MulAccumXAlias<string asm, Instruction inst>
1499 : InstAlias<asm#"\t$dst, $src1, $src2",
1500 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1501 class WideMulAccumAlias<string asm, Instruction inst>
1502 : InstAlias<asm#"\t$dst, $src1, $src2",
1503 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1505 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1506 SDPatternOperator OpNode, string asm>
1507 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1508 asm, "\t$Rd, $Rn, $Rm", "",
1509 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1510 Sched<[WriteISReg, ReadI, ReadISReg]> {
1516 let Inst{30-21} = 0b0011010110;
1517 let Inst{20-16} = Rm;
1518 let Inst{15-13} = 0b010;
1520 let Inst{11-10} = sz;
1523 let Predicates = [HasCRC];
1527 // Address generation.
1530 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1531 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1536 let Inst{31} = page;
1537 let Inst{30-29} = label{1-0};
1538 let Inst{28-24} = 0b10000;
1539 let Inst{23-5} = label{20-2};
1542 let DecoderMethod = "DecodeAdrInstruction";
1549 def movimm32_imm : Operand<i32> {
1550 let ParserMatchClass = Imm0_65535Operand;
1551 let EncoderMethod = "getMoveWideImmOpValue";
1552 let PrintMethod = "printHexImm";
1554 def movimm32_shift : Operand<i32> {
1555 let PrintMethod = "printShifter";
1556 let ParserMatchClass = MovImm32ShifterOperand;
1558 def movimm64_shift : Operand<i32> {
1559 let PrintMethod = "printShifter";
1560 let ParserMatchClass = MovImm64ShifterOperand;
1563 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1564 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1566 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1567 asm, "\t$Rd, $imm$shift", "", []>,
1572 let Inst{30-29} = opc;
1573 let Inst{28-23} = 0b100101;
1574 let Inst{22-21} = shift{5-4};
1575 let Inst{20-5} = imm;
1578 let DecoderMethod = "DecodeMoveImmInstruction";
1581 multiclass MoveImmediate<bits<2> opc, string asm> {
1582 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1586 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1591 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1592 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1594 : I<(outs regtype:$Rd),
1595 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1596 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1597 Sched<[WriteI, ReadI]> {
1601 let Inst{30-29} = opc;
1602 let Inst{28-23} = 0b100101;
1603 let Inst{22-21} = shift{5-4};
1604 let Inst{20-5} = imm;
1607 let DecoderMethod = "DecodeMoveImmInstruction";
1610 multiclass InsertImmediate<bits<2> opc, string asm> {
1611 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1615 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1624 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1625 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1626 string asm, SDPatternOperator OpNode>
1627 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1628 asm, "\t$Rd, $Rn, $imm", "",
1629 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1630 Sched<[WriteI, ReadI]> {
1634 let Inst{30} = isSub;
1635 let Inst{29} = setFlags;
1636 let Inst{28-24} = 0b10001;
1637 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1638 let Inst{21-10} = imm{11-0};
1641 let DecoderMethod = "DecodeBaseAddSubImm";
1644 class BaseAddSubRegPseudo<RegisterClass regtype,
1645 SDPatternOperator OpNode>
1646 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1647 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1648 Sched<[WriteI, ReadI, ReadI]>;
1650 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1651 arith_shifted_reg shifted_regtype, string asm,
1652 SDPatternOperator OpNode>
1653 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1654 asm, "\t$Rd, $Rn, $Rm", "",
1655 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1656 Sched<[WriteISReg, ReadI, ReadISReg]> {
1657 // The operands are in order to match the 'addr' MI operands, so we
1658 // don't need an encoder method and by-name matching. Just use the default
1659 // in-order handling. Since we're using by-order, make sure the names
1665 let Inst{30} = isSub;
1666 let Inst{29} = setFlags;
1667 let Inst{28-24} = 0b01011;
1668 let Inst{23-22} = shift{7-6};
1670 let Inst{20-16} = src2;
1671 let Inst{15-10} = shift{5-0};
1672 let Inst{9-5} = src1;
1673 let Inst{4-0} = dst;
1675 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1678 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1679 RegisterClass src1Regtype, Operand src2Regtype,
1680 string asm, SDPatternOperator OpNode>
1681 : I<(outs dstRegtype:$R1),
1682 (ins src1Regtype:$R2, src2Regtype:$R3),
1683 asm, "\t$R1, $R2, $R3", "",
1684 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1685 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1690 let Inst{30} = isSub;
1691 let Inst{29} = setFlags;
1692 let Inst{28-24} = 0b01011;
1693 let Inst{23-21} = 0b001;
1694 let Inst{20-16} = Rm;
1695 let Inst{15-13} = ext{5-3};
1696 let Inst{12-10} = ext{2-0};
1700 let DecoderMethod = "DecodeAddSubERegInstruction";
1703 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1704 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1705 RegisterClass src1Regtype, RegisterClass src2Regtype,
1706 Operand ext_op, string asm>
1707 : I<(outs dstRegtype:$Rd),
1708 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1709 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1710 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1715 let Inst{30} = isSub;
1716 let Inst{29} = setFlags;
1717 let Inst{28-24} = 0b01011;
1718 let Inst{23-21} = 0b001;
1719 let Inst{20-16} = Rm;
1720 let Inst{15} = ext{5};
1721 let Inst{12-10} = ext{2-0};
1725 let DecoderMethod = "DecodeAddSubERegInstruction";
1728 // Aliases for register+register add/subtract.
1729 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1730 RegisterClass src1Regtype, RegisterClass src2Regtype,
1732 : InstAlias<asm#"\t$dst, $src1, $src2",
1733 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1736 multiclass AddSub<bit isSub, string mnemonic, string alias,
1737 SDPatternOperator OpNode = null_frag> {
1738 let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1739 // Add/Subtract immediate
1740 // Increase the weight of the immediate variant to try to match it before
1741 // the extended register variant.
1742 // We used to match the register variant before the immediate when the
1743 // register argument could be implicitly zero-extended.
1744 let AddedComplexity = 6 in
1745 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1749 let AddedComplexity = 6 in
1750 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1755 // Add/Subtract register - Only used for CodeGen
1756 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1757 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1759 // Add/Subtract shifted register
1760 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1764 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1770 // Add/Subtract extended register
1771 let AddedComplexity = 1, hasSideEffects = 0 in {
1772 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1773 arith_extended_reg32<i32>, mnemonic, OpNode> {
1776 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1777 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1782 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1783 arith_extendlsl64, mnemonic> {
1784 // UXTX and SXTX only.
1785 let Inst{14-13} = 0b11;
1789 // add Rd, Rb, -imm -> sub Rd, Rn, imm
1790 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1791 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1792 addsub_shifted_imm32_neg:$imm), 0>;
1793 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1794 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1795 addsub_shifted_imm64_neg:$imm), 0>;
1797 // Register/register aliases with no shift when SP is not used.
1798 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1799 GPR32, GPR32, GPR32, 0>;
1800 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1801 GPR64, GPR64, GPR64, 0>;
1803 // Register/register aliases with no shift when either the destination or
1804 // first source register is SP.
1805 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1806 GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1807 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1808 GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1809 def : AddSubRegAlias<mnemonic,
1810 !cast<Instruction>(NAME#"Xrx64"),
1811 GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1812 def : AddSubRegAlias<mnemonic,
1813 !cast<Instruction>(NAME#"Xrx64"),
1814 GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1817 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1818 string alias, string cmpAlias> {
1819 let isCompare = 1, Defs = [NZCV] in {
1820 // Add/Subtract immediate
1821 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1825 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1830 // Add/Subtract register
1831 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1832 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1834 // Add/Subtract shifted register
1835 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1839 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1844 // Add/Subtract extended register
1845 let AddedComplexity = 1 in {
1846 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1847 arith_extended_reg32<i32>, mnemonic, OpNode> {
1850 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1851 arith_extended_reg32<i64>, mnemonic, OpNode> {
1856 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1857 arith_extendlsl64, mnemonic> {
1858 // UXTX and SXTX only.
1859 let Inst{14-13} = 0b11;
1864 // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1865 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1866 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1867 addsub_shifted_imm32_neg:$imm), 0>;
1868 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1869 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1870 addsub_shifted_imm64_neg:$imm), 0>;
1873 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1874 WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1875 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1876 XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1877 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1878 WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1879 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1880 XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1881 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1882 XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1883 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1884 WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1885 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1886 XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1888 // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1889 def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1890 WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1891 def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1892 XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1894 // Compare shorthands
1895 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1896 WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1897 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1898 XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1899 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1900 WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1901 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1902 XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1904 // Register/register aliases with no shift when SP is not used.
1905 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1906 GPR32, GPR32, GPR32, 0>;
1907 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1908 GPR64, GPR64, GPR64, 0>;
1910 // Register/register aliases with no shift when the first source register
1912 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1913 GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1914 def : AddSubRegAlias<mnemonic,
1915 !cast<Instruction>(NAME#"Xrx64"),
1916 GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1922 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1924 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1926 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1928 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1929 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1930 Sched<[WriteExtr, ReadExtrHi]> {
1936 let Inst{30-23} = 0b00100111;
1938 let Inst{20-16} = Rm;
1939 let Inst{15-10} = imm;
1944 multiclass ExtractImm<string asm> {
1945 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1947 (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1950 // imm<5> must be zero.
1953 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1955 (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1966 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1967 class BaseBitfieldImm<bits<2> opc,
1968 RegisterClass regtype, Operand imm_type, string asm>
1969 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1970 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1971 Sched<[WriteIS, ReadI]> {
1977 let Inst{30-29} = opc;
1978 let Inst{28-23} = 0b100110;
1979 let Inst{21-16} = immr;
1980 let Inst{15-10} = imms;
1985 multiclass BitfieldImm<bits<2> opc, string asm> {
1986 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1989 // imms<5> and immr<5> must be zero, else ReservedValue().
1993 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1999 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2000 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2001 RegisterClass regtype, Operand imm_type, string asm>
2002 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2004 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2005 Sched<[WriteIS, ReadI]> {
2011 let Inst{30-29} = opc;
2012 let Inst{28-23} = 0b100110;
2013 let Inst{21-16} = immr;
2014 let Inst{15-10} = imms;
2019 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2020 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2023 // imms<5> and immr<5> must be zero, else ReservedValue().
2027 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2037 // Logical (immediate)
2038 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2039 RegisterClass sregtype, Operand imm_type, string asm,
2041 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2042 asm, "\t$Rd, $Rn, $imm", "", pattern>,
2043 Sched<[WriteI, ReadI]> {
2047 let Inst{30-29} = opc;
2048 let Inst{28-23} = 0b100100;
2049 let Inst{22} = imm{12};
2050 let Inst{21-16} = imm{11-6};
2051 let Inst{15-10} = imm{5-0};
2055 let DecoderMethod = "DecodeLogicalImmInstruction";
2058 // Logical (shifted register)
2059 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2060 logical_shifted_reg shifted_regtype, string asm,
2062 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2063 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2064 Sched<[WriteISReg, ReadI, ReadISReg]> {
2065 // The operands are in order to match the 'addr' MI operands, so we
2066 // don't need an encoder method and by-name matching. Just use the default
2067 // in-order handling. Since we're using by-order, make sure the names
2073 let Inst{30-29} = opc;
2074 let Inst{28-24} = 0b01010;
2075 let Inst{23-22} = shift{7-6};
2077 let Inst{20-16} = src2;
2078 let Inst{15-10} = shift{5-0};
2079 let Inst{9-5} = src1;
2080 let Inst{4-0} = dst;
2082 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2085 // Aliases for register+register logical instructions.
2086 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2087 : InstAlias<asm#"\t$dst, $src1, $src2",
2088 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2090 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2092 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2093 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2094 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2095 logical_imm32:$imm))]> {
2097 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2099 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2100 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2101 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2102 logical_imm64:$imm))]> {
2106 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2107 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2108 logical_imm32_not:$imm), 0>;
2109 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2110 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2111 logical_imm64_not:$imm), 0>;
2114 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2116 let isCompare = 1, Defs = [NZCV] in {
2117 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2118 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2120 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2122 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2123 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2126 } // end Defs = [NZCV]
2128 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2129 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2130 logical_imm32_not:$imm), 0>;
2131 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2132 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2133 logical_imm64_not:$imm), 0>;
2136 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2137 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2138 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2139 Sched<[WriteI, ReadI, ReadI]>;
2141 // Split from LogicalImm as not all instructions have both.
2142 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2143 SDPatternOperator OpNode> {
2144 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2145 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2146 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2149 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2150 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2151 logical_shifted_reg32:$Rm))]> {
2154 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2155 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2156 logical_shifted_reg64:$Rm))]> {
2160 def : LogicalRegAlias<mnemonic,
2161 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2162 def : LogicalRegAlias<mnemonic,
2163 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2166 // Split from LogicalReg to allow setting NZCV Defs
2167 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2168 SDPatternOperator OpNode = null_frag> {
2169 let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2170 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2171 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2173 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2174 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2177 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2178 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2183 def : LogicalRegAlias<mnemonic,
2184 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2185 def : LogicalRegAlias<mnemonic,
2186 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2190 // Conditionally set flags
2193 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2194 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2195 string mnemonic, SDNode OpNode>
2196 : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2197 mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2198 [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2199 (i32 imm:$cond), NZCV))]>,
2200 Sched<[WriteI, ReadI]> {
2210 let Inst{29-21} = 0b111010010;
2211 let Inst{20-16} = imm;
2212 let Inst{15-12} = cond;
2213 let Inst{11-10} = 0b10;
2216 let Inst{3-0} = nzcv;
2219 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2220 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2222 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2223 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2224 [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2225 (i32 imm:$cond), NZCV))]>,
2226 Sched<[WriteI, ReadI, ReadI]> {
2236 let Inst{29-21} = 0b111010010;
2237 let Inst{20-16} = Rm;
2238 let Inst{15-12} = cond;
2239 let Inst{11-10} = 0b00;
2242 let Inst{3-0} = nzcv;
2245 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2246 // immediate operand variants
2247 def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2250 def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2253 // register operand variants
2254 def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2257 def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2263 // Conditional select
2266 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2267 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2268 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2270 (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2271 Sched<[WriteI, ReadI, ReadI]> {
2280 let Inst{29-21} = 0b011010100;
2281 let Inst{20-16} = Rm;
2282 let Inst{15-12} = cond;
2283 let Inst{11-10} = op2;
2288 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2289 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2292 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2297 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2299 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2300 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2302 (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2303 (i32 imm:$cond), NZCV))]>,
2304 Sched<[WriteI, ReadI, ReadI]> {
2313 let Inst{29-21} = 0b011010100;
2314 let Inst{20-16} = Rm;
2315 let Inst{15-12} = cond;
2316 let Inst{11-10} = op2;
2321 def inv_cond_XFORM : SDNodeXForm<imm, [{
2322 AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2323 return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2327 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2328 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2331 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2335 def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2336 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2337 (inv_cond_XFORM imm:$cond))>;
2339 def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2340 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2341 (inv_cond_XFORM imm:$cond))>;
2345 // Special Mask Value
2347 def maski8_or_more : Operand<i32>,
2348 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2350 def maski16_or_more : Operand<i32>,
2351 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2359 // (unsigned immediate)
2360 // Indexed for 8-bit registers. offset is in range [0,4095].
2361 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2362 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2363 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2364 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2365 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2367 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2368 let Name = "UImm12Offset" # Scale;
2369 let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2370 let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2371 let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2374 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2375 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2376 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2377 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2378 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2380 class uimm12_scaled<int Scale> : Operand<i64> {
2381 let ParserMatchClass
2382 = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2384 = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2385 let PrintMethod = "printUImm12Offset<" # Scale # ">";
2388 def uimm12s1 : uimm12_scaled<1>;
2389 def uimm12s2 : uimm12_scaled<2>;
2390 def uimm12s4 : uimm12_scaled<4>;
2391 def uimm12s8 : uimm12_scaled<8>;
2392 def uimm12s16 : uimm12_scaled<16>;
2394 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2395 string asm, list<dag> pattern>
2396 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2402 let Inst{31-30} = sz;
2403 let Inst{29-27} = 0b111;
2405 let Inst{25-24} = 0b01;
2406 let Inst{23-22} = opc;
2407 let Inst{21-10} = offset;
2411 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2414 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2415 Operand indextype, string asm, list<dag> pattern> {
2416 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2417 def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2418 (ins GPR64sp:$Rn, indextype:$offset),
2422 def : InstAlias<asm # "\t$Rt, [$Rn]",
2423 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2426 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2427 Operand indextype, string asm, list<dag> pattern> {
2428 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2429 def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2430 (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2434 def : InstAlias<asm # "\t$Rt, [$Rn]",
2435 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2438 def PrefetchOperand : AsmOperandClass {
2439 let Name = "Prefetch";
2440 let ParserMethod = "tryParsePrefetch";
2442 def prfop : Operand<i32> {
2443 let PrintMethod = "printPrefetchOp";
2444 let ParserMatchClass = PrefetchOperand;
2447 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2448 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2449 : BaseLoadStoreUI<sz, V, opc,
2450 (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2458 // Load literal address: 19-bit immediate. The low two bits of the target
2459 // offset are implied zero and so are not part of the immediate.
2460 def am_ldrlit : Operand<OtherVT> {
2461 let EncoderMethod = "getLoadLiteralOpValue";
2462 let DecoderMethod = "DecodePCRelLabel19";
2463 let PrintMethod = "printAlignedLabel";
2464 let ParserMatchClass = PCRelLabel19Operand;
2467 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2468 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2469 : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2470 asm, "\t$Rt, $label", "", []>,
2474 let Inst{31-30} = opc;
2475 let Inst{29-27} = 0b011;
2477 let Inst{25-24} = 0b00;
2478 let Inst{23-5} = label;
2482 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2483 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2484 : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2485 asm, "\t$Rt, $label", "", pat>,
2489 let Inst{31-30} = opc;
2490 let Inst{29-27} = 0b011;
2492 let Inst{25-24} = 0b00;
2493 let Inst{23-5} = label;
2498 // Load/store register offset
2501 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2502 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2503 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2504 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2505 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2507 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2508 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2509 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2510 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2511 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2513 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2514 let Name = "Mem" # Reg # "Extend" # Width;
2515 let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2516 let RenderMethod = "addMemExtendOperands";
2517 let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2520 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2521 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2522 // the trivial shift.
2523 let RenderMethod = "addMemExtend8Operands";
2525 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2526 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2527 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2528 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2530 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2531 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2532 // the trivial shift.
2533 let RenderMethod = "addMemExtend8Operands";
2535 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2536 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2537 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2538 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2540 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2542 let ParserMatchClass = ParserClass;
2543 let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2544 let DecoderMethod = "DecodeMemExtend";
2545 let EncoderMethod = "getMemExtendOpValue";
2546 let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2549 def ro_Wextend8 : ro_extend<MemWExtend8Operand, "w", 8>;
2550 def ro_Wextend16 : ro_extend<MemWExtend16Operand, "w", 16>;
2551 def ro_Wextend32 : ro_extend<MemWExtend32Operand, "w", 32>;
2552 def ro_Wextend64 : ro_extend<MemWExtend64Operand, "w", 64>;
2553 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2555 def ro_Xextend8 : ro_extend<MemXExtend8Operand, "x", 8>;
2556 def ro_Xextend16 : ro_extend<MemXExtend16Operand, "x", 16>;
2557 def ro_Xextend32 : ro_extend<MemXExtend32Operand, "x", 32>;
2558 def ro_Xextend64 : ro_extend<MemXExtend64Operand, "x", 64>;
2559 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2561 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2562 Operand wextend, Operand xextend> {
2563 // CodeGen-level pattern covering the entire addressing mode.
2564 ComplexPattern Wpat = windex;
2565 ComplexPattern Xpat = xindex;
2567 // Asm-level Operand covering the valid "uxtw #3" style syntax.
2568 Operand Wext = wextend;
2569 Operand Xext = xextend;
2572 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2573 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2574 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2575 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2576 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2579 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2580 string asm, dag ins, dag outs, list<dag> pat>
2581 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2586 let Inst{31-30} = sz;
2587 let Inst{29-27} = 0b111;
2589 let Inst{25-24} = 0b00;
2590 let Inst{23-22} = opc;
2592 let Inst{20-16} = Rm;
2593 let Inst{15} = extend{1}; // sign extend Rm?
2595 let Inst{12} = extend{0}; // do shift?
2596 let Inst{11-10} = 0b10;
2601 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2602 : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2603 (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2605 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2606 string asm, ValueType Ty, SDPatternOperator loadop> {
2607 let AddedComplexity = 10 in
2608 def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2610 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2611 [(set (Ty regtype:$Rt),
2612 (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2613 ro_Wextend8:$extend)))]>,
2614 Sched<[WriteLDIdx, ReadAdrBase]> {
2618 let AddedComplexity = 10 in
2619 def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2621 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2622 [(set (Ty regtype:$Rt),
2623 (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2624 ro_Xextend8:$extend)))]>,
2625 Sched<[WriteLDIdx, ReadAdrBase]> {
2629 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2632 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2633 string asm, ValueType Ty, SDPatternOperator storeop> {
2634 let AddedComplexity = 10 in
2635 def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2636 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2637 [(storeop (Ty regtype:$Rt),
2638 (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2639 ro_Wextend8:$extend))]>,
2640 Sched<[WriteSTIdx, ReadAdrBase]> {
2644 let AddedComplexity = 10 in
2645 def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2646 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2647 [(storeop (Ty regtype:$Rt),
2648 (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2649 ro_Xextend8:$extend))]>,
2650 Sched<[WriteSTIdx, ReadAdrBase]> {
2654 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2657 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2658 string asm, dag ins, dag outs, list<dag> pat>
2659 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2664 let Inst{31-30} = sz;
2665 let Inst{29-27} = 0b111;
2667 let Inst{25-24} = 0b00;
2668 let Inst{23-22} = opc;
2670 let Inst{20-16} = Rm;
2671 let Inst{15} = extend{1}; // sign extend Rm?
2673 let Inst{12} = extend{0}; // do shift?
2674 let Inst{11-10} = 0b10;
2679 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2680 string asm, ValueType Ty, SDPatternOperator loadop> {
2681 let AddedComplexity = 10 in
2682 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2683 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2684 [(set (Ty regtype:$Rt),
2685 (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2686 ro_Wextend16:$extend)))]>,
2687 Sched<[WriteLDIdx, ReadAdrBase]> {
2691 let AddedComplexity = 10 in
2692 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2693 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2694 [(set (Ty regtype:$Rt),
2695 (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2696 ro_Xextend16:$extend)))]>,
2697 Sched<[WriteLDIdx, ReadAdrBase]> {
2701 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2704 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2705 string asm, ValueType Ty, SDPatternOperator storeop> {
2706 let AddedComplexity = 10 in
2707 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2708 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2709 [(storeop (Ty regtype:$Rt),
2710 (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2711 ro_Wextend16:$extend))]>,
2712 Sched<[WriteSTIdx, ReadAdrBase]> {
2716 let AddedComplexity = 10 in
2717 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2718 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2719 [(storeop (Ty regtype:$Rt),
2720 (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2721 ro_Xextend16:$extend))]>,
2722 Sched<[WriteSTIdx, ReadAdrBase]> {
2726 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2729 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2730 string asm, dag ins, dag outs, list<dag> pat>
2731 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2736 let Inst{31-30} = sz;
2737 let Inst{29-27} = 0b111;
2739 let Inst{25-24} = 0b00;
2740 let Inst{23-22} = opc;
2742 let Inst{20-16} = Rm;
2743 let Inst{15} = extend{1}; // sign extend Rm?
2745 let Inst{12} = extend{0}; // do shift?
2746 let Inst{11-10} = 0b10;
2751 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2752 string asm, ValueType Ty, SDPatternOperator loadop> {
2753 let AddedComplexity = 10 in
2754 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2755 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2756 [(set (Ty regtype:$Rt),
2757 (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2758 ro_Wextend32:$extend)))]>,
2759 Sched<[WriteLDIdx, ReadAdrBase]> {
2763 let AddedComplexity = 10 in
2764 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2765 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2766 [(set (Ty regtype:$Rt),
2767 (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2768 ro_Xextend32:$extend)))]>,
2769 Sched<[WriteLDIdx, ReadAdrBase]> {
2773 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2776 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2777 string asm, ValueType Ty, SDPatternOperator storeop> {
2778 let AddedComplexity = 10 in
2779 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2780 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2781 [(storeop (Ty regtype:$Rt),
2782 (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2783 ro_Wextend32:$extend))]>,
2784 Sched<[WriteSTIdx, ReadAdrBase]> {
2788 let AddedComplexity = 10 in
2789 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2790 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2791 [(storeop (Ty regtype:$Rt),
2792 (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2793 ro_Xextend32:$extend))]>,
2794 Sched<[WriteSTIdx, ReadAdrBase]> {
2798 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2801 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2802 string asm, dag ins, dag outs, list<dag> pat>
2803 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2808 let Inst{31-30} = sz;
2809 let Inst{29-27} = 0b111;
2811 let Inst{25-24} = 0b00;
2812 let Inst{23-22} = opc;
2814 let Inst{20-16} = Rm;
2815 let Inst{15} = extend{1}; // sign extend Rm?
2817 let Inst{12} = extend{0}; // do shift?
2818 let Inst{11-10} = 0b10;
2823 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2824 string asm, ValueType Ty, SDPatternOperator loadop> {
2825 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2826 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2827 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2828 [(set (Ty regtype:$Rt),
2829 (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2830 ro_Wextend64:$extend)))]>,
2831 Sched<[WriteLDIdx, ReadAdrBase]> {
2835 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2836 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2837 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2838 [(set (Ty regtype:$Rt),
2839 (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2840 ro_Xextend64:$extend)))]>,
2841 Sched<[WriteLDIdx, ReadAdrBase]> {
2845 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2848 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2849 string asm, ValueType Ty, SDPatternOperator storeop> {
2850 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2851 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2852 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2853 [(storeop (Ty regtype:$Rt),
2854 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2855 ro_Wextend64:$extend))]>,
2856 Sched<[WriteSTIdx, ReadAdrBase]> {
2860 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2861 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2862 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2863 [(storeop (Ty regtype:$Rt),
2864 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2865 ro_Xextend64:$extend))]>,
2866 Sched<[WriteSTIdx, ReadAdrBase]> {
2870 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2873 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2874 string asm, dag ins, dag outs, list<dag> pat>
2875 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2880 let Inst{31-30} = sz;
2881 let Inst{29-27} = 0b111;
2883 let Inst{25-24} = 0b00;
2884 let Inst{23-22} = opc;
2886 let Inst{20-16} = Rm;
2887 let Inst{15} = extend{1}; // sign extend Rm?
2889 let Inst{12} = extend{0}; // do shift?
2890 let Inst{11-10} = 0b10;
2895 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2896 string asm, ValueType Ty, SDPatternOperator loadop> {
2897 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2898 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2899 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2900 [(set (Ty regtype:$Rt),
2901 (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2902 ro_Wextend128:$extend)))]>,
2903 Sched<[WriteLDIdx, ReadAdrBase]> {
2907 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2908 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2909 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2910 [(set (Ty regtype:$Rt),
2911 (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2912 ro_Xextend128:$extend)))]>,
2913 Sched<[WriteLDIdx, ReadAdrBase]> {
2917 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2920 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2921 string asm, ValueType Ty, SDPatternOperator storeop> {
2922 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2923 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2924 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2925 [(storeop (Ty regtype:$Rt),
2926 (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2927 ro_Wextend128:$extend))]>,
2928 Sched<[WriteSTIdx, ReadAdrBase]> {
2932 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2933 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2934 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2935 [(storeop (Ty regtype:$Rt),
2936 (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2937 ro_Xextend128:$extend))]>,
2938 Sched<[WriteSTIdx, ReadAdrBase]> {
2942 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2945 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2946 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2947 string asm, list<dag> pat>
2948 : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2954 let Inst{31-30} = sz;
2955 let Inst{29-27} = 0b111;
2957 let Inst{25-24} = 0b00;
2958 let Inst{23-22} = opc;
2960 let Inst{20-16} = Rm;
2961 let Inst{15} = extend{1}; // sign extend Rm?
2963 let Inst{12} = extend{0}; // do shift?
2964 let Inst{11-10} = 0b10;
2969 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2970 def roW : BasePrefetchRO<sz, V, opc, (outs),
2971 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2972 asm, [(AArch64Prefetch imm:$Rt,
2973 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2974 ro_Wextend64:$extend))]> {
2978 def roX : BasePrefetchRO<sz, V, opc, (outs),
2979 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2980 asm, [(AArch64Prefetch imm:$Rt,
2981 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2982 ro_Xextend64:$extend))]> {
2986 def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2987 (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2988 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2992 // Load/store unscaled immediate
2995 def am_unscaled8 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2996 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2997 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2998 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2999 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3001 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3002 string asm, list<dag> pattern>
3003 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3007 let Inst{31-30} = sz;
3008 let Inst{29-27} = 0b111;
3010 let Inst{25-24} = 0b00;
3011 let Inst{23-22} = opc;
3013 let Inst{20-12} = offset;
3014 let Inst{11-10} = 0b00;
3018 let DecoderMethod = "DecodeSignedLdStInstruction";
3021 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3022 string asm, list<dag> pattern> {
3023 let AddedComplexity = 1 in // try this before LoadUI
3024 def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3025 (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3028 def : InstAlias<asm # "\t$Rt, [$Rn]",
3029 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3032 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3033 string asm, list<dag> pattern> {
3034 let AddedComplexity = 1 in // try this before StoreUI
3035 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3036 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3040 def : InstAlias<asm # "\t$Rt, [$Rn]",
3041 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3044 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3046 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3047 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3048 (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3052 def : InstAlias<asm # "\t$Rt, [$Rn]",
3053 (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3057 // Load/store unscaled immediate, unprivileged
3060 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3061 dag oops, dag iops, string asm>
3062 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3066 let Inst{31-30} = sz;
3067 let Inst{29-27} = 0b111;
3069 let Inst{25-24} = 0b00;
3070 let Inst{23-22} = opc;
3072 let Inst{20-12} = offset;
3073 let Inst{11-10} = 0b10;
3077 let DecoderMethod = "DecodeSignedLdStInstruction";
3080 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3081 RegisterClass regtype, string asm> {
3082 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3083 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3084 (ins GPR64sp:$Rn, simm9:$offset), asm>,
3087 def : InstAlias<asm # "\t$Rt, [$Rn]",
3088 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3091 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3092 RegisterClass regtype, string asm> {
3093 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3094 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3095 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3099 def : InstAlias<asm # "\t$Rt, [$Rn]",
3100 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3104 // Load/store pre-indexed
3107 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3108 string asm, string cstr, list<dag> pat>
3109 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3113 let Inst{31-30} = sz;
3114 let Inst{29-27} = 0b111;
3116 let Inst{25-24} = 0;
3117 let Inst{23-22} = opc;
3119 let Inst{20-12} = offset;
3120 let Inst{11-10} = 0b11;
3124 let DecoderMethod = "DecodeSignedLdStInstruction";
3127 let hasSideEffects = 0 in {
3128 let mayStore = 0, mayLoad = 1 in
3129 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3131 : BaseLoadStorePreIdx<sz, V, opc,
3132 (outs GPR64sp:$wback, regtype:$Rt),
3133 (ins GPR64sp:$Rn, simm9:$offset), asm,
3134 "$Rn = $wback,@earlyclobber $wback", []>,
3135 Sched<[WriteLD, WriteAdr]>;
3137 let mayStore = 1, mayLoad = 0 in
3138 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3139 string asm, SDPatternOperator storeop, ValueType Ty>
3140 : BaseLoadStorePreIdx<sz, V, opc,
3141 (outs GPR64sp:$wback),
3142 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3143 asm, "$Rn = $wback,@earlyclobber $wback",
3144 [(set GPR64sp:$wback,
3145 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3146 Sched<[WriteAdr, WriteST]>;
3147 } // hasSideEffects = 0
3150 // Load/store post-indexed
3153 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3154 string asm, string cstr, list<dag> pat>
3155 : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3159 let Inst{31-30} = sz;
3160 let Inst{29-27} = 0b111;
3162 let Inst{25-24} = 0b00;
3163 let Inst{23-22} = opc;
3165 let Inst{20-12} = offset;
3166 let Inst{11-10} = 0b01;
3170 let DecoderMethod = "DecodeSignedLdStInstruction";
3173 let hasSideEffects = 0 in {
3174 let mayStore = 0, mayLoad = 1 in
3175 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3177 : BaseLoadStorePostIdx<sz, V, opc,
3178 (outs GPR64sp:$wback, regtype:$Rt),
3179 (ins GPR64sp:$Rn, simm9:$offset),
3180 asm, "$Rn = $wback,@earlyclobber $wback", []>,
3181 Sched<[WriteLD, WriteI]>;
3183 let mayStore = 1, mayLoad = 0 in
3184 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3185 string asm, SDPatternOperator storeop, ValueType Ty>
3186 : BaseLoadStorePostIdx<sz, V, opc,
3187 (outs GPR64sp:$wback),
3188 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3189 asm, "$Rn = $wback,@earlyclobber $wback",
3190 [(set GPR64sp:$wback,
3191 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3192 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3193 } // hasSideEffects = 0
3200 // (indexed, offset)
3202 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3204 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3209 let Inst{31-30} = opc;
3210 let Inst{29-27} = 0b101;
3212 let Inst{25-23} = 0b010;
3214 let Inst{21-15} = offset;
3215 let Inst{14-10} = Rt2;
3219 let DecoderMethod = "DecodePairLdStInstruction";
3222 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3223 Operand indextype, string asm> {
3224 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3225 def i : BaseLoadStorePairOffset<opc, V, 1,
3226 (outs regtype:$Rt, regtype:$Rt2),
3227 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3228 Sched<[WriteLD, WriteLDHi]>;
3230 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3231 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3236 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3237 Operand indextype, string asm> {
3238 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3239 def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3240 (ins regtype:$Rt, regtype:$Rt2,
3241 GPR64sp:$Rn, indextype:$offset),
3245 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3246 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3251 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3253 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3258 let Inst{31-30} = opc;
3259 let Inst{29-27} = 0b101;
3261 let Inst{25-23} = 0b011;
3263 let Inst{21-15} = offset;
3264 let Inst{14-10} = Rt2;
3268 let DecoderMethod = "DecodePairLdStInstruction";
3271 let hasSideEffects = 0 in {
3272 let mayStore = 0, mayLoad = 1 in
3273 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3274 Operand indextype, string asm>
3275 : BaseLoadStorePairPreIdx<opc, V, 1,
3276 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3277 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3278 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3280 let mayStore = 1, mayLoad = 0 in
3281 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3282 Operand indextype, string asm>
3283 : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3284 (ins regtype:$Rt, regtype:$Rt2,
3285 GPR64sp:$Rn, indextype:$offset),
3287 Sched<[WriteAdr, WriteSTP]>;
3288 } // hasSideEffects = 0
3292 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3294 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3299 let Inst{31-30} = opc;
3300 let Inst{29-27} = 0b101;
3302 let Inst{25-23} = 0b001;
3304 let Inst{21-15} = offset;
3305 let Inst{14-10} = Rt2;
3309 let DecoderMethod = "DecodePairLdStInstruction";
3312 let hasSideEffects = 0 in {
3313 let mayStore = 0, mayLoad = 1 in
3314 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3315 Operand idxtype, string asm>
3316 : BaseLoadStorePairPostIdx<opc, V, 1,
3317 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3318 (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3319 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3321 let mayStore = 1, mayLoad = 0 in
3322 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3323 Operand idxtype, string asm>
3324 : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3325 (ins regtype:$Rt, regtype:$Rt2,
3326 GPR64sp:$Rn, idxtype:$offset),
3328 Sched<[WriteAdr, WriteSTP]>;
3329 } // hasSideEffects = 0
3333 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3335 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3340 let Inst{31-30} = opc;
3341 let Inst{29-27} = 0b101;
3343 let Inst{25-23} = 0b000;
3345 let Inst{21-15} = offset;
3346 let Inst{14-10} = Rt2;
3350 let DecoderMethod = "DecodePairLdStInstruction";
3353 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3354 Operand indextype, string asm> {
3355 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3356 def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3357 (outs regtype:$Rt, regtype:$Rt2),
3358 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3359 Sched<[WriteLD, WriteLDHi]>;
3362 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3363 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3367 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3368 Operand indextype, string asm> {
3369 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3370 def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3371 (ins regtype:$Rt, regtype:$Rt2,
3372 GPR64sp:$Rn, indextype:$offset),
3376 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3377 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3382 // Load/store exclusive
3385 // True exclusive operations write to and/or read from the system's exclusive
3386 // monitors, which as far as a compiler is concerned can be modelled as a
3387 // random shared memory address. Hence LoadExclusive mayStore.
3389 // Since these instructions have the undefined register bits set to 1 in
3390 // their canonical form, we need a post encoder method to set those bits
3391 // to 1 when encoding these instructions. We do this using the
3392 // fixLoadStoreExclusive function. This function has template parameters:
3394 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3396 // hasRs indicates that the instruction uses the Rs field, so we won't set
3397 // it to 1 (and the same for Rt2). We don't need template parameters for
3398 // the other register fields since Rt and Rn are always used.
3400 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3401 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3402 dag oops, dag iops, string asm, string operands>
3403 : I<oops, iops, asm, operands, "", []> {
3404 let Inst{31-30} = sz;
3405 let Inst{29-24} = 0b001000;
3411 let DecoderMethod = "DecodeExclusiveLdStInstruction";
3414 // Neither Rs nor Rt2 operands.
3415 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3416 dag oops, dag iops, string asm, string operands>
3417 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3420 let Inst{20-16} = 0b11111;
3421 let Unpredictable{20-16} = 0b11111;
3422 let Inst{14-10} = 0b11111;
3423 let Unpredictable{14-10} = 0b11111;
3427 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3430 // Simple load acquires don't set the exclusive monitor
3431 let mayLoad = 1, mayStore = 0 in
3432 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3433 RegisterClass regtype, string asm>
3434 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3435 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3438 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3439 RegisterClass regtype, string asm>
3440 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3441 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3444 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3445 RegisterClass regtype, string asm>
3446 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3447 (outs regtype:$Rt, regtype:$Rt2),
3448 (ins GPR64sp0:$Rn), asm,
3449 "\t$Rt, $Rt2, [$Rn]">,
3450 Sched<[WriteLD, WriteLDHi]> {
3454 let Inst{14-10} = Rt2;
3458 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3461 // Simple store release operations do not check the exclusive monitor.
3462 let mayLoad = 0, mayStore = 1 in
3463 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3464 RegisterClass regtype, string asm>
3465 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3466 (ins regtype:$Rt, GPR64sp0:$Rn),
3467 asm, "\t$Rt, [$Rn]">,
3470 let mayLoad = 1, mayStore = 1 in
3471 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3472 RegisterClass regtype, string asm>
3473 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3474 (ins regtype:$Rt, GPR64sp0:$Rn),
3475 asm, "\t$Ws, $Rt, [$Rn]">,
3480 let Inst{20-16} = Ws;
3484 let Constraints = "@earlyclobber $Ws";
3485 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3488 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3489 RegisterClass regtype, string asm>
3490 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3492 (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3493 asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3499 let Inst{20-16} = Ws;
3500 let Inst{14-10} = Rt2;
3504 let Constraints = "@earlyclobber $Ws";
3508 // Exception generation
3511 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3512 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3513 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3516 let Inst{31-24} = 0b11010100;
3517 let Inst{23-21} = op1;
3518 let Inst{20-5} = imm;
3519 let Inst{4-2} = 0b000;
3523 let Predicates = [HasFPARMv8] in {
3526 // Floating point to integer conversion
3529 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3530 RegisterClass srcType, RegisterClass dstType,
3531 string asm, list<dag> pattern>
3532 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3533 asm, "\t$Rd, $Rn", "", pattern>,
3534 Sched<[WriteFCvt]> {
3537 let Inst{30-29} = 0b00;
3538 let Inst{28-24} = 0b11110;
3539 let Inst{23-22} = type;
3541 let Inst{20-19} = rmode;
3542 let Inst{18-16} = opcode;
3543 let Inst{15-10} = 0;
3548 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3549 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3550 RegisterClass srcType, RegisterClass dstType,
3551 Operand immType, string asm, list<dag> pattern>
3552 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3553 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3554 Sched<[WriteFCvt]> {
3558 let Inst{30-29} = 0b00;
3559 let Inst{28-24} = 0b11110;
3560 let Inst{23-22} = type;
3562 let Inst{20-19} = rmode;
3563 let Inst{18-16} = opcode;
3564 let Inst{15-10} = scale;
3569 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3570 SDPatternOperator OpN> {
3571 // Unscaled half-precision to 32-bit
3572 def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
3573 [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
3574 let Inst{31} = 0; // 32-bit GPR flag
3575 let Predicates = [HasFullFP16];
3578 // Unscaled half-precision to 64-bit
3579 def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
3580 [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
3581 let Inst{31} = 1; // 64-bit GPR flag
3582 let Predicates = [HasFullFP16];
3585 // Unscaled single-precision to 32-bit
3586 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3587 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3588 let Inst{31} = 0; // 32-bit GPR flag
3591 // Unscaled single-precision to 64-bit
3592 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3593 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3594 let Inst{31} = 1; // 64-bit GPR flag
3597 // Unscaled double-precision to 32-bit
3598 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3599 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3600 let Inst{31} = 0; // 32-bit GPR flag
3603 // Unscaled double-precision to 64-bit
3604 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3605 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3606 let Inst{31} = 1; // 64-bit GPR flag
3610 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3611 SDPatternOperator OpN> {
3612 // Scaled half-precision to 32-bit
3613 def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
3614 fixedpoint_f16_i32, asm,
3615 [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
3616 fixedpoint_f16_i32:$scale)))]> {
3617 let Inst{31} = 0; // 32-bit GPR flag
3619 let Predicates = [HasFullFP16];
3622 // Scaled half-precision to 64-bit
3623 def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
3624 fixedpoint_f16_i64, asm,
3625 [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
3626 fixedpoint_f16_i64:$scale)))]> {
3627 let Inst{31} = 1; // 64-bit GPR flag
3628 let Predicates = [HasFullFP16];
3631 // Scaled single-precision to 32-bit
3632 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3633 fixedpoint_f32_i32, asm,
3634 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3635 fixedpoint_f32_i32:$scale)))]> {
3636 let Inst{31} = 0; // 32-bit GPR flag
3640 // Scaled single-precision to 64-bit
3641 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3642 fixedpoint_f32_i64, asm,
3643 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3644 fixedpoint_f32_i64:$scale)))]> {
3645 let Inst{31} = 1; // 64-bit GPR flag
3648 // Scaled double-precision to 32-bit
3649 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3650 fixedpoint_f64_i32, asm,
3651 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3652 fixedpoint_f64_i32:$scale)))]> {
3653 let Inst{31} = 0; // 32-bit GPR flag
3657 // Scaled double-precision to 64-bit
3658 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3659 fixedpoint_f64_i64, asm,
3660 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3661 fixedpoint_f64_i64:$scale)))]> {
3662 let Inst{31} = 1; // 64-bit GPR flag
3667 // Integer to floating point conversion
3670 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3671 class BaseIntegerToFP<bit isUnsigned,
3672 RegisterClass srcType, RegisterClass dstType,
3673 Operand immType, string asm, list<dag> pattern>
3674 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3675 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3676 Sched<[WriteFCvt]> {
3680 let Inst{30-24} = 0b0011110;
3681 let Inst{21-17} = 0b00001;
3682 let Inst{16} = isUnsigned;
3683 let Inst{15-10} = scale;
3688 class BaseIntegerToFPUnscaled<bit isUnsigned,
3689 RegisterClass srcType, RegisterClass dstType,
3690 ValueType dvt, string asm, SDNode node>
3691 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3692 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3693 Sched<[WriteFCvt]> {
3697 let Inst{30-24} = 0b0011110;
3698 let Inst{21-17} = 0b10001;
3699 let Inst{16} = isUnsigned;
3700 let Inst{15-10} = 0b000000;
3705 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3707 def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
3708 let Inst{31} = 0; // 32-bit GPR flag
3709 let Inst{23-22} = 0b11; // 16-bit FPR flag
3710 let Predicates = [HasFullFP16];
3713 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3714 let Inst{31} = 0; // 32-bit GPR flag
3715 let Inst{23-22} = 0b00; // 32-bit FPR flag
3718 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3719 let Inst{31} = 0; // 32-bit GPR flag
3720 let Inst{23-22} = 0b01; // 64-bit FPR flag
3723 def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
3724 let Inst{31} = 1; // 64-bit GPR flag
3725 let Inst{23-22} = 0b11; // 16-bit FPR flag
3726 let Predicates = [HasFullFP16];
3729 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3730 let Inst{31} = 1; // 64-bit GPR flag
3731 let Inst{23-22} = 0b00; // 32-bit FPR flag
3734 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3735 let Inst{31} = 1; // 64-bit GPR flag
3736 let Inst{23-22} = 0b01; // 64-bit FPR flag
3740 def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
3742 (fdiv (node GPR32:$Rn),
3743 fixedpoint_f16_i32:$scale))]> {
3744 let Inst{31} = 0; // 32-bit GPR flag
3745 let Inst{23-22} = 0b11; // 16-bit FPR flag
3747 let Predicates = [HasFullFP16];
3750 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3752 (fdiv (node GPR32:$Rn),
3753 fixedpoint_f32_i32:$scale))]> {
3754 let Inst{31} = 0; // 32-bit GPR flag
3755 let Inst{23-22} = 0b00; // 32-bit FPR flag
3759 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3761 (fdiv (node GPR32:$Rn),
3762 fixedpoint_f64_i32:$scale))]> {
3763 let Inst{31} = 0; // 32-bit GPR flag
3764 let Inst{23-22} = 0b01; // 64-bit FPR flag
3768 def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
3770 (fdiv (node GPR64:$Rn),
3771 fixedpoint_f16_i64:$scale))]> {
3772 let Inst{31} = 1; // 64-bit GPR flag
3773 let Inst{23-22} = 0b11; // 16-bit FPR flag
3774 let Predicates = [HasFullFP16];
3777 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3779 (fdiv (node GPR64:$Rn),
3780 fixedpoint_f32_i64:$scale))]> {
3781 let Inst{31} = 1; // 64-bit GPR flag
3782 let Inst{23-22} = 0b00; // 32-bit FPR flag
3785 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3787 (fdiv (node GPR64:$Rn),
3788 fixedpoint_f64_i64:$scale))]> {
3789 let Inst{31} = 1; // 64-bit GPR flag
3790 let Inst{23-22} = 0b01; // 64-bit FPR flag
3795 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3798 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3799 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3800 RegisterClass srcType, RegisterClass dstType,
3802 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3803 // We use COPY_TO_REGCLASS for these bitconvert operations.
3804 // copyPhysReg() expands the resultant COPY instructions after
3805 // regalloc is done. This gives greater freedom for the allocator
3806 // and related passes (coalescing, copy propagation, et. al.) to
3807 // be more effective.
3808 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3809 Sched<[WriteFCopy]> {
3812 let Inst{30-24} = 0b0011110;
3814 let Inst{20-19} = rmode;
3815 let Inst{18-16} = opcode;
3816 let Inst{15-10} = 0b000000;
3821 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3822 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3823 RegisterClass srcType, RegisterOperand dstType, string asm,
3825 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3826 "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3827 Sched<[WriteFCopy]> {
3830 let Inst{30-23} = 0b00111101;
3832 let Inst{20-19} = rmode;
3833 let Inst{18-16} = opcode;
3834 let Inst{15-10} = 0b000000;
3838 let DecoderMethod = "DecodeFMOVLaneInstruction";
3841 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3842 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3843 RegisterOperand srcType, RegisterClass dstType, string asm,
3845 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3846 "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3847 Sched<[WriteFCopy]> {
3850 let Inst{30-23} = 0b00111101;
3852 let Inst{20-19} = rmode;
3853 let Inst{18-16} = opcode;
3854 let Inst{15-10} = 0b000000;
3858 let DecoderMethod = "DecodeFMOVLaneInstruction";
3862 multiclass UnscaledConversion<string asm> {
3863 def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
3864 let Inst{31} = 0; // 32-bit GPR flag
3865 let Inst{23-22} = 0b11; // 16-bit FPR flag
3866 let Predicates = [HasFullFP16];
3869 def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
3870 let Inst{31} = 1; // 64-bit GPR flag
3871 let Inst{23-22} = 0b11; // 16-bit FPR flag
3872 let Predicates = [HasFullFP16];
3875 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3876 let Inst{31} = 0; // 32-bit GPR flag
3877 let Inst{23-22} = 0b00; // 32-bit FPR flag
3880 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3881 let Inst{31} = 1; // 64-bit GPR flag
3882 let Inst{23-22} = 0b01; // 64-bit FPR flag
3885 def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
3886 let Inst{31} = 0; // 32-bit GPR flag
3887 let Inst{23-22} = 0b11; // 16-bit FPR flag
3888 let Predicates = [HasFullFP16];
3891 def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
3892 let Inst{31} = 1; // 64-bit GPR flag
3893 let Inst{23-22} = 0b11; // 16-bit FPR flag
3894 let Predicates = [HasFullFP16];
3897 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3898 let Inst{31} = 0; // 32-bit GPR flag
3899 let Inst{23-22} = 0b00; // 32-bit FPR flag
3902 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3903 let Inst{31} = 1; // 64-bit GPR flag
3904 let Inst{23-22} = 0b01; // 64-bit FPR flag
3907 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3913 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3921 // Floating point conversion
3924 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3925 RegisterClass srcType, string asm, list<dag> pattern>
3926 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3927 Sched<[WriteFCvt]> {
3930 let Inst{31-24} = 0b00011110;
3931 let Inst{23-22} = type;
3932 let Inst{21-17} = 0b10001;
3933 let Inst{16-15} = opcode;
3934 let Inst{14-10} = 0b10000;
3939 multiclass FPConversion<string asm> {
3940 // Double-precision to Half-precision
3941 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3942 [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3944 // Double-precision to Single-precision
3945 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3946 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3948 // Half-precision to Double-precision
3949 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3950 [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3952 // Half-precision to Single-precision
3953 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3954 [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3956 // Single-precision to Double-precision
3957 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3958 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3960 // Single-precision to Half-precision
3961 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3962 [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3966 // Single operand floating point data processing
3969 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3970 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3971 ValueType vt, string asm, SDPatternOperator node>
3972 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3973 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3977 let Inst{31-24} = 0b00011110;
3978 let Inst{21-19} = 0b100;
3979 let Inst{18-15} = opcode;
3980 let Inst{14-10} = 0b10000;
3985 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3986 SDPatternOperator node = null_frag> {
3987 def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
3988 let Inst{23-22} = 0b11; // 16-bit size flag
3989 let Predicates = [HasFullFP16];
3992 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3993 let Inst{23-22} = 0b00; // 32-bit size flag
3996 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3997 let Inst{23-22} = 0b01; // 64-bit size flag
4002 // Two operand floating point data processing
4005 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4006 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4007 string asm, list<dag> pat>
4008 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4009 asm, "\t$Rd, $Rn, $Rm", "", pat>,
4014 let Inst{31-24} = 0b00011110;
4016 let Inst{20-16} = Rm;
4017 let Inst{15-12} = opcode;
4018 let Inst{11-10} = 0b10;
4023 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4024 SDPatternOperator node = null_frag> {
4025 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4026 [(set (f16 FPR16:$Rd),
4027 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4028 let Inst{23-22} = 0b11; // 16-bit size flag
4029 let Predicates = [HasFullFP16];
4032 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4033 [(set (f32 FPR32:$Rd),
4034 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4035 let Inst{23-22} = 0b00; // 32-bit size flag
4038 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4039 [(set (f64 FPR64:$Rd),
4040 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4041 let Inst{23-22} = 0b01; // 64-bit size flag
4045 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4046 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4047 [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4048 let Inst{23-22} = 0b11; // 16-bit size flag
4049 let Predicates = [HasFullFP16];
4052 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4053 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4054 let Inst{23-22} = 0b00; // 32-bit size flag
4057 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4058 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4059 let Inst{23-22} = 0b01; // 64-bit size flag
4065 // Three operand floating point data processing
4068 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4069 RegisterClass regtype, string asm, list<dag> pat>
4070 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4071 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4072 Sched<[WriteFMul]> {
4077 let Inst{31-24} = 0b00011111;
4078 let Inst{21} = isNegated;
4079 let Inst{20-16} = Rm;
4080 let Inst{15} = isSub;
4081 let Inst{14-10} = Ra;
4086 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4087 SDPatternOperator node> {
4088 def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4090 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4091 let Inst{23-22} = 0b11; // 16-bit size flag
4092 let Predicates = [HasFullFP16];
4095 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4097 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4098 let Inst{23-22} = 0b00; // 32-bit size flag
4101 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4103 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4104 let Inst{23-22} = 0b01; // 64-bit size flag
4109 // Floating point data comparisons
4112 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4113 class BaseOneOperandFPComparison<bit signalAllNans,
4114 RegisterClass regtype, string asm,
4116 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4117 Sched<[WriteFCmp]> {
4119 let Inst{31-24} = 0b00011110;
4122 let Inst{15-10} = 0b001000;
4124 let Inst{4} = signalAllNans;
4125 let Inst{3-0} = 0b1000;
4127 // Rm should be 0b00000 canonically, but we need to accept any value.
4128 let PostEncoderMethod = "fixOneOperandFPComparison";
4131 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4132 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4133 string asm, list<dag> pat>
4134 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4135 Sched<[WriteFCmp]> {
4138 let Inst{31-24} = 0b00011110;
4140 let Inst{20-16} = Rm;
4141 let Inst{15-10} = 0b001000;
4143 let Inst{4} = signalAllNans;
4144 let Inst{3-0} = 0b0000;
4147 multiclass FPComparison<bit signalAllNans, string asm,
4148 SDPatternOperator OpNode = null_frag> {
4149 let Defs = [NZCV] in {
4150 def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4151 [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4152 let Inst{23-22} = 0b11;
4153 let Predicates = [HasFullFP16];
4156 def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4157 [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4158 let Inst{23-22} = 0b11;
4159 let Predicates = [HasFullFP16];
4162 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4163 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4164 let Inst{23-22} = 0b00;
4167 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4168 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4169 let Inst{23-22} = 0b00;
4172 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4173 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4174 let Inst{23-22} = 0b01;
4177 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4178 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4179 let Inst{23-22} = 0b01;
4185 // Floating point conditional comparisons
4188 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4189 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4190 string mnemonic, list<dag> pat>
4191 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4192 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4193 Sched<[WriteFCmp]> {
4202 let Inst{31-24} = 0b00011110;
4204 let Inst{20-16} = Rm;
4205 let Inst{15-12} = cond;
4206 let Inst{11-10} = 0b01;
4208 let Inst{4} = signalAllNans;
4209 let Inst{3-0} = nzcv;
4212 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4213 SDPatternOperator OpNode = null_frag> {
4214 def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4215 let Inst{23-22} = 0b11;
4216 let Predicates = [HasFullFP16];
4219 def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4220 [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4221 (i32 imm:$cond), NZCV))]> {
4222 let Inst{23-22} = 0b00;
4225 def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4226 [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4227 (i32 imm:$cond), NZCV))]> {
4228 let Inst{23-22} = 0b01;
4233 // Floating point conditional select
4236 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4237 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4238 asm, "\t$Rd, $Rn, $Rm, $cond", "",
4240 (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4241 (i32 imm:$cond), NZCV))]>,
4248 let Inst{31-24} = 0b00011110;
4250 let Inst{20-16} = Rm;
4251 let Inst{15-12} = cond;
4252 let Inst{11-10} = 0b11;
4257 multiclass FPCondSelect<string asm> {
4258 let Uses = [NZCV] in {
4259 def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4260 let Inst{23-22} = 0b11;
4261 let Predicates = [HasFullFP16];
4264 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4265 let Inst{23-22} = 0b00;
4268 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4269 let Inst{23-22} = 0b01;
4275 // Floating move immediate
4278 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4279 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4280 [(set regtype:$Rd, fpimmtype:$imm)]>,
4281 Sched<[WriteFImm]> {
4284 let Inst{31-24} = 0b00011110;
4286 let Inst{20-13} = imm;
4287 let Inst{12-5} = 0b10000000;
4291 multiclass FPMoveImmediate<string asm> {
4292 def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4293 let Inst{23-22} = 0b11;
4294 let Predicates = [HasFullFP16];
4297 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4298 let Inst{23-22} = 0b00;
4301 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4302 let Inst{23-22} = 0b01;
4305 } // end of 'let Predicates = [HasFPARMv8]'
4307 //----------------------------------------------------------------------------
4309 //----------------------------------------------------------------------------
4311 let Predicates = [HasNEON] in {
4313 //----------------------------------------------------------------------------
4314 // AdvSIMD three register vector instructions
4315 //----------------------------------------------------------------------------
4317 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4318 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4319 RegisterOperand regtype, string asm, string kind,
4321 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4322 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4323 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4331 let Inst{28-24} = 0b01110;
4332 let Inst{23-21} = size;
4333 let Inst{20-16} = Rm;
4334 let Inst{15-11} = opcode;
4340 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4341 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4342 RegisterOperand regtype, string asm, string kind,
4344 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4345 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4346 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4354 let Inst{28-24} = 0b01110;
4355 let Inst{23-21} = size;
4356 let Inst{20-16} = Rm;
4357 let Inst{15-11} = opcode;
4363 // All operand sizes distinguished in the encoding.
4364 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4365 SDPatternOperator OpNode> {
4366 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4368 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4369 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4371 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4372 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4374 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4375 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4377 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4378 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4380 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4381 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4383 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4384 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4386 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4389 // As above, but D sized elements unsupported.
4390 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4391 SDPatternOperator OpNode> {
4392 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4394 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4395 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4397 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4398 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4400 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4401 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4403 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4404 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4406 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4407 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4409 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4412 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4413 SDPatternOperator OpNode> {
4414 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
4416 [(set (v8i8 V64:$dst),
4417 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4418 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
4420 [(set (v16i8 V128:$dst),
4421 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4422 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
4424 [(set (v4i16 V64:$dst),
4425 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4426 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
4428 [(set (v8i16 V128:$dst),
4429 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4430 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
4432 [(set (v2i32 V64:$dst),
4433 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4434 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
4436 [(set (v4i32 V128:$dst),
4437 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4440 // As above, but only B sized elements supported.
4441 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4442 SDPatternOperator OpNode> {
4443 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4445 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4446 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4448 [(set (v16i8 V128:$Rd),
4449 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4452 // As above, but only floating point elements supported.
4453 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
4454 string asm, SDPatternOperator OpNode> {
4455 let Predicates = [HasNEON, HasFullFP16] in {
4456 def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4458 [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4459 def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4461 [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4462 } // Predicates = [HasNEON, HasFullFP16]
4463 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4465 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4466 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4468 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4469 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4471 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4474 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
4476 SDPatternOperator OpNode> {
4477 let Predicates = [HasNEON, HasFullFP16] in {
4478 def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4480 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4481 def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4483 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4484 } // Predicates = [HasNEON, HasFullFP16]
4485 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4487 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4488 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4490 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4491 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4493 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4496 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
4497 string asm, SDPatternOperator OpNode> {
4498 let Predicates = [HasNEON, HasFullFP16] in {
4499 def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
4501 [(set (v4f16 V64:$dst),
4502 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4503 def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
4505 [(set (v8f16 V128:$dst),
4506 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4507 } // Predicates = [HasNEON, HasFullFP16]
4508 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
4510 [(set (v2f32 V64:$dst),
4511 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4512 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
4514 [(set (v4f32 V128:$dst),
4515 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4516 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
4518 [(set (v2f64 V128:$dst),
4519 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4522 // As above, but D and B sized elements unsupported.
4523 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4524 SDPatternOperator OpNode> {
4525 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4527 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4528 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4530 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4531 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4533 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4534 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4536 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4539 // Logical three vector ops share opcode bits, and only use B sized elements.
4540 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4541 SDPatternOperator OpNode = null_frag> {
4542 def v8i8 : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
4544 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4545 def v16i8 : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
4547 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4549 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4550 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4551 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4552 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4553 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4554 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4556 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4557 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4558 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4559 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4560 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4561 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4564 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4565 string asm, SDPatternOperator OpNode> {
4566 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
4568 [(set (v8i8 V64:$dst),
4569 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4570 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
4572 [(set (v16i8 V128:$dst),
4573 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4574 (v16i8 V128:$Rm)))]>;
4576 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4578 (!cast<Instruction>(NAME#"v8i8")
4579 V64:$LHS, V64:$MHS, V64:$RHS)>;
4580 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4582 (!cast<Instruction>(NAME#"v8i8")
4583 V64:$LHS, V64:$MHS, V64:$RHS)>;
4584 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4586 (!cast<Instruction>(NAME#"v8i8")
4587 V64:$LHS, V64:$MHS, V64:$RHS)>;
4589 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4590 (v8i16 V128:$RHS))),
4591 (!cast<Instruction>(NAME#"v16i8")
4592 V128:$LHS, V128:$MHS, V128:$RHS)>;
4593 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4594 (v4i32 V128:$RHS))),
4595 (!cast<Instruction>(NAME#"v16i8")
4596 V128:$LHS, V128:$MHS, V128:$RHS)>;
4597 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4598 (v2i64 V128:$RHS))),
4599 (!cast<Instruction>(NAME#"v16i8")
4600 V128:$LHS, V128:$MHS, V128:$RHS)>;
4604 //----------------------------------------------------------------------------
4605 // AdvSIMD two register vector instructions.
4606 //----------------------------------------------------------------------------
4608 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4609 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4610 bits<2> size2, RegisterOperand regtype, string asm,
4611 string dstkind, string srckind, list<dag> pattern>
4612 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4613 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4614 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4621 let Inst{28-24} = 0b01110;
4622 let Inst{23-22} = size;
4624 let Inst{20-19} = size2;
4625 let Inst{18-17} = 0b00;
4626 let Inst{16-12} = opcode;
4627 let Inst{11-10} = 0b10;
4632 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4633 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4634 bits<2> size2, RegisterOperand regtype,
4635 string asm, string dstkind, string srckind,
4637 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4638 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4639 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4646 let Inst{28-24} = 0b01110;
4647 let Inst{23-22} = size;
4649 let Inst{20-19} = size2;
4650 let Inst{18-17} = 0b00;
4651 let Inst{16-12} = opcode;
4652 let Inst{11-10} = 0b10;
4657 // Supports B, H, and S element sizes.
4658 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4659 SDPatternOperator OpNode> {
4660 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4662 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4663 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4664 asm, ".16b", ".16b",
4665 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4666 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4668 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4669 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4671 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4672 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4674 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4675 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4677 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4680 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4681 RegisterOperand regtype, string asm, string dstkind,
4682 string srckind, string amount>
4683 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4684 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4685 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4691 let Inst{29-24} = 0b101110;
4692 let Inst{23-22} = size;
4693 let Inst{21-10} = 0b100001001110;
4698 multiclass SIMDVectorLShiftLongBySizeBHS {
4699 let hasSideEffects = 0 in {
4700 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4701 "shll", ".8h", ".8b", "8">;
4702 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4703 "shll2", ".8h", ".16b", "8">;
4704 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4705 "shll", ".4s", ".4h", "16">;
4706 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4707 "shll2", ".4s", ".8h", "16">;
4708 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4709 "shll", ".2d", ".2s", "32">;
4710 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4711 "shll2", ".2d", ".4s", "32">;
4715 // Supports all element sizes.
4716 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4717 SDPatternOperator OpNode> {
4718 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4720 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4721 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4723 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4724 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4726 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4727 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4729 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4730 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4732 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4733 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4735 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4738 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4739 SDPatternOperator OpNode> {
4740 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
4742 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4744 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
4746 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4747 (v16i8 V128:$Rn)))]>;
4748 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
4750 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4751 (v4i16 V64:$Rn)))]>;
4752 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
4754 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4755 (v8i16 V128:$Rn)))]>;
4756 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
4758 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4759 (v2i32 V64:$Rn)))]>;
4760 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
4762 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4763 (v4i32 V128:$Rn)))]>;
4766 // Supports all element sizes, except 1xD.
4767 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4768 SDPatternOperator OpNode> {
4769 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
4771 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4772 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
4773 asm, ".16b", ".16b",
4774 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4775 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
4777 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4778 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
4780 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4781 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
4783 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4784 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
4786 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4787 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
4789 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4792 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4793 SDPatternOperator OpNode = null_frag> {
4794 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4796 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4797 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4798 asm, ".16b", ".16b",
4799 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4800 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4802 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4803 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4805 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4806 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4808 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4809 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4811 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4812 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
4814 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4818 // Supports only B element sizes.
4819 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4820 SDPatternOperator OpNode> {
4821 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
4823 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4824 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
4825 asm, ".16b", ".16b",
4826 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4830 // Supports only B and H element sizes.
4831 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4832 SDPatternOperator OpNode> {
4833 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4835 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4836 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4837 asm, ".16b", ".16b",
4838 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4839 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4841 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4842 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4844 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4847 // Supports only S and D element sizes, uses high bit of the size field
4848 // as an extra opcode bit.
4849 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4850 SDPatternOperator OpNode> {
4851 let Predicates = [HasNEON, HasFullFP16] in {
4852 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4854 [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
4855 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4857 [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
4858 } // Predicates = [HasNEON, HasFullFP16]
4859 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4861 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4862 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4864 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4865 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4867 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4870 // Supports only S element size.
4871 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4872 SDPatternOperator OpNode> {
4873 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4875 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4876 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4878 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4882 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4883 SDPatternOperator OpNode> {
4884 let Predicates = [HasNEON, HasFullFP16] in {
4885 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4887 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
4888 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4890 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
4891 } // Predicates = [HasNEON, HasFullFP16]
4892 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4894 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4895 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4897 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4898 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4900 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4903 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4904 SDPatternOperator OpNode> {
4905 let Predicates = [HasNEON, HasFullFP16] in {
4906 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4908 [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4909 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4911 [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4912 } // Predicates = [HasNEON, HasFullFP16]
4913 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4915 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4916 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4918 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4919 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4921 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4925 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4926 RegisterOperand inreg, RegisterOperand outreg,
4927 string asm, string outkind, string inkind,
4929 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4930 "{\t$Rd" # outkind # ", $Rn" # inkind #
4931 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4938 let Inst{28-24} = 0b01110;
4939 let Inst{23-22} = size;
4940 let Inst{21-17} = 0b10000;
4941 let Inst{16-12} = opcode;
4942 let Inst{11-10} = 0b10;
4947 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4948 RegisterOperand inreg, RegisterOperand outreg,
4949 string asm, string outkind, string inkind,
4951 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4952 "{\t$Rd" # outkind # ", $Rn" # inkind #
4953 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4960 let Inst{28-24} = 0b01110;
4961 let Inst{23-22} = size;
4962 let Inst{21-17} = 0b10000;
4963 let Inst{16-12} = opcode;
4964 let Inst{11-10} = 0b10;
4969 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4970 SDPatternOperator OpNode> {
4971 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4973 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4974 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4975 asm#"2", ".16b", ".8h", []>;
4976 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4978 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4979 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4980 asm#"2", ".8h", ".4s", []>;
4981 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4983 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4984 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4985 asm#"2", ".4s", ".2d", []>;
4987 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4988 (!cast<Instruction>(NAME # "v16i8")
4989 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4990 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4991 (!cast<Instruction>(NAME # "v8i16")
4992 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4993 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4994 (!cast<Instruction>(NAME # "v4i32")
4995 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4998 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
4999 bits<5> opcode, RegisterOperand regtype, string asm,
5000 string kind, string zero, ValueType dty,
5001 ValueType sty, SDNode OpNode>
5002 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5003 "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5004 "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5005 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5012 let Inst{28-24} = 0b01110;
5013 let Inst{23-22} = size;
5015 let Inst{20-19} = size2;
5016 let Inst{18-17} = 0b00;
5017 let Inst{16-12} = opcode;
5018 let Inst{11-10} = 0b10;
5023 // Comparisons support all element sizes, except 1xD.
5024 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5026 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5028 v8i8, v8i8, OpNode>;
5029 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5031 v16i8, v16i8, OpNode>;
5032 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5034 v4i16, v4i16, OpNode>;
5035 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5037 v8i16, v8i16, OpNode>;
5038 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5040 v2i32, v2i32, OpNode>;
5041 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5043 v4i32, v4i32, OpNode>;
5044 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5046 v2i64, v2i64, OpNode>;
5049 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5050 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5051 string asm, SDNode OpNode> {
5053 let Predicates = [HasNEON, HasFullFP16] in {
5054 def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5056 v4i16, v4f16, OpNode>;
5057 def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5059 v8i16, v8f16, OpNode>;
5060 } // Predicates = [HasNEON, HasFullFP16]
5061 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5063 v2i32, v2f32, OpNode>;
5064 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5066 v4i32, v4f32, OpNode>;
5067 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5069 v2i64, v2f64, OpNode>;
5071 let Predicates = [HasNEON, HasFullFP16] in {
5072 def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5073 (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5074 def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5075 (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5077 def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5078 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5079 def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5080 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5081 def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5082 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5083 let Predicates = [HasNEON, HasFullFP16] in {
5084 def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5085 (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5086 def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5087 (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5089 def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5090 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5091 def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5092 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5093 def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5094 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5097 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5098 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5099 RegisterOperand outtype, RegisterOperand intype,
5100 string asm, string VdTy, string VnTy,
5102 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5103 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5110 let Inst{28-24} = 0b01110;
5111 let Inst{23-22} = size;
5112 let Inst{21-17} = 0b10000;
5113 let Inst{16-12} = opcode;
5114 let Inst{11-10} = 0b10;
5119 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5120 RegisterOperand outtype, RegisterOperand intype,
5121 string asm, string VdTy, string VnTy,
5123 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5124 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5131 let Inst{28-24} = 0b01110;
5132 let Inst{23-22} = size;
5133 let Inst{21-17} = 0b10000;
5134 let Inst{16-12} = opcode;
5135 let Inst{11-10} = 0b10;
5140 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5141 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5142 asm, ".4s", ".4h", []>;
5143 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5144 asm#"2", ".4s", ".8h", []>;
5145 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5146 asm, ".2d", ".2s", []>;
5147 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5148 asm#"2", ".2d", ".4s", []>;
5151 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5152 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5153 asm, ".4h", ".4s", []>;
5154 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5155 asm#"2", ".8h", ".4s", []>;
5156 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5157 asm, ".2s", ".2d", []>;
5158 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5159 asm#"2", ".4s", ".2d", []>;
5162 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5164 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5166 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5167 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5168 asm#"2", ".4s", ".2d", []>;
5170 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5171 (!cast<Instruction>(NAME # "v4f32")
5172 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5175 //----------------------------------------------------------------------------
5176 // AdvSIMD three register different-size vector instructions.
5177 //----------------------------------------------------------------------------
5179 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5180 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5181 RegisterOperand outtype, RegisterOperand intype1,
5182 RegisterOperand intype2, string asm,
5183 string outkind, string inkind1, string inkind2,
5185 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5186 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5187 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5193 let Inst{30} = size{0};
5195 let Inst{28-24} = 0b01110;
5196 let Inst{23-22} = size{2-1};
5198 let Inst{20-16} = Rm;
5199 let Inst{15-12} = opcode;
5200 let Inst{11-10} = 0b00;
5205 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5206 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5207 RegisterOperand outtype, RegisterOperand intype1,
5208 RegisterOperand intype2, string asm,
5209 string outkind, string inkind1, string inkind2,
5211 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5212 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5213 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5219 let Inst{30} = size{0};
5221 let Inst{28-24} = 0b01110;
5222 let Inst{23-22} = size{2-1};
5224 let Inst{20-16} = Rm;
5225 let Inst{15-12} = opcode;
5226 let Inst{11-10} = 0b00;
5231 // FIXME: TableGen doesn't know how to deal with expanded types that also
5232 // change the element count (in this case, placing the results in
5233 // the high elements of the result register rather than the low
5234 // elements). Until that's fixed, we can't code-gen those.
5235 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5237 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5239 asm, ".8b", ".8h", ".8h",
5240 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5241 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5243 asm#"2", ".16b", ".8h", ".8h",
5245 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5247 asm, ".4h", ".4s", ".4s",
5248 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5249 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5251 asm#"2", ".8h", ".4s", ".4s",
5253 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5255 asm, ".2s", ".2d", ".2d",
5256 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5257 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5259 asm#"2", ".4s", ".2d", ".2d",
5263 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5264 // a version attached to an instruction.
5265 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5267 (!cast<Instruction>(NAME # "v8i16_v16i8")
5268 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5269 V128:$Rn, V128:$Rm)>;
5270 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5272 (!cast<Instruction>(NAME # "v4i32_v8i16")
5273 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5274 V128:$Rn, V128:$Rm)>;
5275 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5277 (!cast<Instruction>(NAME # "v2i64_v4i32")
5278 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5279 V128:$Rn, V128:$Rm)>;
5282 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5284 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5286 asm, ".8h", ".8b", ".8b",
5287 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5288 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5290 asm#"2", ".8h", ".16b", ".16b", []>;
5291 let Predicates = [HasCrypto] in {
5292 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5294 asm, ".1q", ".1d", ".1d", []>;
5295 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5297 asm#"2", ".1q", ".2d", ".2d", []>;
5300 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5301 (v8i8 (extract_high_v16i8 V128:$Rm)))),
5302 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5305 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5306 SDPatternOperator OpNode> {
5307 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5309 asm, ".4s", ".4h", ".4h",
5310 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5311 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5313 asm#"2", ".4s", ".8h", ".8h",
5314 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5315 (extract_high_v8i16 V128:$Rm)))]>;
5316 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5318 asm, ".2d", ".2s", ".2s",
5319 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5320 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5322 asm#"2", ".2d", ".4s", ".4s",
5323 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5324 (extract_high_v4i32 V128:$Rm)))]>;
5327 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5328 SDPatternOperator OpNode = null_frag> {
5329 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5331 asm, ".8h", ".8b", ".8b",
5332 [(set (v8i16 V128:$Rd),
5333 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5334 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5336 asm#"2", ".8h", ".16b", ".16b",
5337 [(set (v8i16 V128:$Rd),
5338 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5339 (extract_high_v16i8 V128:$Rm)))))]>;
5340 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5342 asm, ".4s", ".4h", ".4h",
5343 [(set (v4i32 V128:$Rd),
5344 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5345 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5347 asm#"2", ".4s", ".8h", ".8h",
5348 [(set (v4i32 V128:$Rd),
5349 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5350 (extract_high_v8i16 V128:$Rm)))))]>;
5351 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5353 asm, ".2d", ".2s", ".2s",
5354 [(set (v2i64 V128:$Rd),
5355 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5356 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5358 asm#"2", ".2d", ".4s", ".4s",
5359 [(set (v2i64 V128:$Rd),
5360 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5361 (extract_high_v4i32 V128:$Rm)))))]>;
5364 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5366 SDPatternOperator OpNode> {
5367 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5369 asm, ".8h", ".8b", ".8b",
5370 [(set (v8i16 V128:$dst),
5371 (add (v8i16 V128:$Rd),
5372 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5373 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5375 asm#"2", ".8h", ".16b", ".16b",
5376 [(set (v8i16 V128:$dst),
5377 (add (v8i16 V128:$Rd),
5378 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5379 (extract_high_v16i8 V128:$Rm))))))]>;
5380 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5382 asm, ".4s", ".4h", ".4h",
5383 [(set (v4i32 V128:$dst),
5384 (add (v4i32 V128:$Rd),
5385 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5386 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5388 asm#"2", ".4s", ".8h", ".8h",
5389 [(set (v4i32 V128:$dst),
5390 (add (v4i32 V128:$Rd),
5391 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5392 (extract_high_v8i16 V128:$Rm))))))]>;
5393 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5395 asm, ".2d", ".2s", ".2s",
5396 [(set (v2i64 V128:$dst),
5397 (add (v2i64 V128:$Rd),
5398 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5399 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5401 asm#"2", ".2d", ".4s", ".4s",
5402 [(set (v2i64 V128:$dst),
5403 (add (v2i64 V128:$Rd),
5404 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5405 (extract_high_v4i32 V128:$Rm))))))]>;
5408 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5409 SDPatternOperator OpNode = null_frag> {
5410 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5412 asm, ".8h", ".8b", ".8b",
5413 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5414 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5416 asm#"2", ".8h", ".16b", ".16b",
5417 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5418 (extract_high_v16i8 V128:$Rm)))]>;
5419 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5421 asm, ".4s", ".4h", ".4h",
5422 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5423 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5425 asm#"2", ".4s", ".8h", ".8h",
5426 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5427 (extract_high_v8i16 V128:$Rm)))]>;
5428 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5430 asm, ".2d", ".2s", ".2s",
5431 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5432 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5434 asm#"2", ".2d", ".4s", ".4s",
5435 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5436 (extract_high_v4i32 V128:$Rm)))]>;
5439 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5441 SDPatternOperator OpNode> {
5442 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5444 asm, ".8h", ".8b", ".8b",
5445 [(set (v8i16 V128:$dst),
5446 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5447 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5449 asm#"2", ".8h", ".16b", ".16b",
5450 [(set (v8i16 V128:$dst),
5451 (OpNode (v8i16 V128:$Rd),
5452 (extract_high_v16i8 V128:$Rn),
5453 (extract_high_v16i8 V128:$Rm)))]>;
5454 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5456 asm, ".4s", ".4h", ".4h",
5457 [(set (v4i32 V128:$dst),
5458 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5459 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5461 asm#"2", ".4s", ".8h", ".8h",
5462 [(set (v4i32 V128:$dst),
5463 (OpNode (v4i32 V128:$Rd),
5464 (extract_high_v8i16 V128:$Rn),
5465 (extract_high_v8i16 V128:$Rm)))]>;
5466 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5468 asm, ".2d", ".2s", ".2s",
5469 [(set (v2i64 V128:$dst),
5470 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5471 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5473 asm#"2", ".2d", ".4s", ".4s",
5474 [(set (v2i64 V128:$dst),
5475 (OpNode (v2i64 V128:$Rd),
5476 (extract_high_v4i32 V128:$Rn),
5477 (extract_high_v4i32 V128:$Rm)))]>;
5480 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5481 SDPatternOperator Accum> {
5482 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5484 asm, ".4s", ".4h", ".4h",
5485 [(set (v4i32 V128:$dst),
5486 (Accum (v4i32 V128:$Rd),
5487 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5488 (v4i16 V64:$Rm)))))]>;
5489 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5491 asm#"2", ".4s", ".8h", ".8h",
5492 [(set (v4i32 V128:$dst),
5493 (Accum (v4i32 V128:$Rd),
5494 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5495 (extract_high_v8i16 V128:$Rm)))))]>;
5496 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5498 asm, ".2d", ".2s", ".2s",
5499 [(set (v2i64 V128:$dst),
5500 (Accum (v2i64 V128:$Rd),
5501 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5502 (v2i32 V64:$Rm)))))]>;
5503 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5505 asm#"2", ".2d", ".4s", ".4s",
5506 [(set (v2i64 V128:$dst),
5507 (Accum (v2i64 V128:$Rd),
5508 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5509 (extract_high_v4i32 V128:$Rm)))))]>;
5512 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5513 SDPatternOperator OpNode> {
5514 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5516 asm, ".8h", ".8h", ".8b",
5517 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5518 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5520 asm#"2", ".8h", ".8h", ".16b",
5521 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5522 (extract_high_v16i8 V128:$Rm)))]>;
5523 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5525 asm, ".4s", ".4s", ".4h",
5526 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5527 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5529 asm#"2", ".4s", ".4s", ".8h",
5530 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5531 (extract_high_v8i16 V128:$Rm)))]>;
5532 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5534 asm, ".2d", ".2d", ".2s",
5535 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5536 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5538 asm#"2", ".2d", ".2d", ".4s",
5539 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5540 (extract_high_v4i32 V128:$Rm)))]>;
5543 //----------------------------------------------------------------------------
5544 // AdvSIMD bitwise extract from vector
5545 //----------------------------------------------------------------------------
5547 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5548 string asm, string kind>
5549 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5550 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5551 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5552 [(set (vty regtype:$Rd),
5553 (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5560 let Inst{30} = size;
5561 let Inst{29-21} = 0b101110000;
5562 let Inst{20-16} = Rm;
5564 let Inst{14-11} = imm;
5571 multiclass SIMDBitwiseExtract<string asm> {
5572 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5575 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5578 //----------------------------------------------------------------------------
5579 // AdvSIMD zip vector
5580 //----------------------------------------------------------------------------
5582 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5583 string asm, string kind, SDNode OpNode, ValueType valty>
5584 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5585 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5586 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5587 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5593 let Inst{30} = size{0};
5594 let Inst{29-24} = 0b001110;
5595 let Inst{23-22} = size{2-1};
5597 let Inst{20-16} = Rm;
5599 let Inst{14-12} = opc;
5600 let Inst{11-10} = 0b10;
5605 multiclass SIMDZipVector<bits<3>opc, string asm,
5607 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
5608 asm, ".8b", OpNode, v8i8>;
5609 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
5610 asm, ".16b", OpNode, v16i8>;
5611 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
5612 asm, ".4h", OpNode, v4i16>;
5613 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
5614 asm, ".8h", OpNode, v8i16>;
5615 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
5616 asm, ".2s", OpNode, v2i32>;
5617 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
5618 asm, ".4s", OpNode, v4i32>;
5619 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
5620 asm, ".2d", OpNode, v2i64>;
5622 def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5623 (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5624 def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5625 (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5626 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5627 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5628 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5629 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5630 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5631 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5634 //----------------------------------------------------------------------------
5635 // AdvSIMD three register scalar instructions
5636 //----------------------------------------------------------------------------
5638 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5639 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
5640 RegisterClass regtype, string asm,
5642 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5643 "\t$Rd, $Rn, $Rm", "", pattern>,
5648 let Inst{31-30} = 0b01;
5650 let Inst{28-24} = 0b11110;
5651 let Inst{23-21} = size;
5652 let Inst{20-16} = Rm;
5653 let Inst{15-11} = opcode;
5659 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5660 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5661 dag oops, dag iops, string asm,
5663 : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5668 let Inst{31-30} = 0b01;
5670 let Inst{28-24} = 0b11110;
5671 let Inst{23-22} = size;
5673 let Inst{20-16} = Rm;
5674 let Inst{15-11} = opcode;
5680 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5681 SDPatternOperator OpNode> {
5682 def v1i64 : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
5683 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5686 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5687 SDPatternOperator OpNode> {
5688 def v1i64 : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
5689 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5690 def v1i32 : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
5691 def v1i16 : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
5692 def v1i8 : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
5694 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5695 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5696 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5697 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5700 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5701 SDPatternOperator OpNode> {
5702 def v1i32 : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
5703 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5704 def v1i16 : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
5707 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5708 SDPatternOperator OpNode = null_frag> {
5709 def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5710 (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
5712 def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5713 (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
5717 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
5718 SDPatternOperator OpNode = null_frag> {
5719 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5720 def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
5721 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5722 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
5723 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5724 let Predicates = [HasNEON, HasFullFP16] in {
5725 def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
5726 [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
5727 } // Predicates = [HasNEON, HasFullFP16]
5730 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5731 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5734 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
5735 SDPatternOperator OpNode = null_frag> {
5736 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5737 def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
5738 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5739 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
5740 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5741 let Predicates = [HasNEON, HasFullFP16] in {
5742 def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
5744 } // Predicates = [HasNEON, HasFullFP16]
5747 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5748 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5751 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5752 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5753 : I<oops, iops, asm,
5754 "\t$Rd, $Rn, $Rm", cstr, pat>,
5759 let Inst{31-30} = 0b01;
5761 let Inst{28-24} = 0b11110;
5762 let Inst{23-22} = size;
5764 let Inst{20-16} = Rm;
5765 let Inst{15-11} = opcode;
5771 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5772 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5773 SDPatternOperator OpNode = null_frag> {
5774 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5776 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5777 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5779 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5780 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5783 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5784 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5785 SDPatternOperator OpNode = null_frag> {
5786 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5788 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5789 asm, "$Rd = $dst", []>;
5790 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5792 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5794 [(set (i64 FPR64:$dst),
5795 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5798 //----------------------------------------------------------------------------
5799 // AdvSIMD two register scalar instructions
5800 //----------------------------------------------------------------------------
5802 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5803 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
5804 RegisterClass regtype, RegisterClass regtype2,
5805 string asm, list<dag> pat>
5806 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5807 "\t$Rd, $Rn", "", pat>,
5811 let Inst{31-30} = 0b01;
5813 let Inst{28-24} = 0b11110;
5814 let Inst{23-22} = size;
5816 let Inst{20-19} = size2;
5817 let Inst{18-17} = 0b00;
5818 let Inst{16-12} = opcode;
5819 let Inst{11-10} = 0b10;
5824 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5825 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5826 RegisterClass regtype, RegisterClass regtype2,
5827 string asm, list<dag> pat>
5828 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5829 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5833 let Inst{31-30} = 0b01;
5835 let Inst{28-24} = 0b11110;
5836 let Inst{23-22} = size;
5837 let Inst{21-17} = 0b10000;
5838 let Inst{16-12} = opcode;
5839 let Inst{11-10} = 0b10;
5845 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5846 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
5847 RegisterClass regtype, string asm, string zero>
5848 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5849 "\t$Rd, $Rn, #" # zero, "", []>,
5853 let Inst{31-30} = 0b01;
5855 let Inst{28-24} = 0b11110;
5856 let Inst{23-22} = size;
5858 let Inst{20-19} = size2;
5859 let Inst{18-17} = 0b00;
5860 let Inst{16-12} = opcode;
5861 let Inst{11-10} = 0b10;
5866 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5867 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5868 [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5872 let Inst{31-17} = 0b011111100110000;
5873 let Inst{16-12} = opcode;
5874 let Inst{11-10} = 0b10;
5879 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5880 SDPatternOperator OpNode> {
5881 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
5883 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5884 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5887 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
5888 SDPatternOperator OpNode> {
5889 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
5890 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
5891 let Predicates = [HasNEON, HasFullFP16] in {
5892 def v1i16rz : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
5895 def : InstAlias<asm # "\t$Rd, $Rn, #0",
5896 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5897 def : InstAlias<asm # "\t$Rd, $Rn, #0",
5898 (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5899 let Predicates = [HasNEON, HasFullFP16] in {
5900 def : InstAlias<asm # "\t$Rd, $Rn, #0",
5901 (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
5904 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5905 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5908 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5909 SDPatternOperator OpNode = null_frag> {
5910 def v1i64 : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
5911 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5913 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5914 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5917 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
5918 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
5919 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
5920 let Predicates = [HasNEON, HasFullFP16] in {
5921 def v1f16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
5925 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
5926 SDPatternOperator OpNode> {
5927 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
5928 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5929 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
5930 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5931 let Predicates = [HasNEON, HasFullFP16] in {
5932 def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
5933 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
5937 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5938 SDPatternOperator OpNode = null_frag> {
5939 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5940 def v1i64 : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
5941 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5942 def v1i32 : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
5943 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5944 def v1i16 : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
5945 def v1i8 : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
5948 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5949 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5952 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5954 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5955 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5956 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5957 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5958 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5959 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5960 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5963 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5964 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5969 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5970 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5971 SDPatternOperator OpNode = null_frag> {
5972 def v1i32 : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
5973 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5974 def v1i16 : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
5975 def v1i8 : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
5978 //----------------------------------------------------------------------------
5979 // AdvSIMD scalar pairwise instructions
5980 //----------------------------------------------------------------------------
5982 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5983 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5984 RegisterOperand regtype, RegisterOperand vectype,
5985 string asm, string kind>
5986 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5987 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5991 let Inst{31-30} = 0b01;
5993 let Inst{28-24} = 0b11110;
5994 let Inst{23-22} = size;
5995 let Inst{21-17} = 0b11000;
5996 let Inst{16-12} = opcode;
5997 let Inst{11-10} = 0b10;
6002 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6003 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6007 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6008 let Predicates = [HasNEON, HasFullFP16] in {
6009 def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6012 def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6014 def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6018 //----------------------------------------------------------------------------
6019 // AdvSIMD across lanes instructions
6020 //----------------------------------------------------------------------------
6022 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6023 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6024 RegisterClass regtype, RegisterOperand vectype,
6025 string asm, string kind, list<dag> pattern>
6026 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6027 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6034 let Inst{28-24} = 0b01110;
6035 let Inst{23-22} = size;
6036 let Inst{21-17} = 0b11000;
6037 let Inst{16-12} = opcode;
6038 let Inst{11-10} = 0b10;
6043 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6045 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
6047 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
6049 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6051 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6053 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6057 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6058 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6060 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6062 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6064 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6066 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6070 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6072 let Predicates = [HasNEON, HasFullFP16] in {
6073 def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6075 [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6076 def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6078 [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6079 } // Predicates = [HasNEON, HasFullFP16]
6080 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6082 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6085 //----------------------------------------------------------------------------
6086 // AdvSIMD INS/DUP instructions
6087 //----------------------------------------------------------------------------
6089 // FIXME: There has got to be a better way to factor these. ugh.
6091 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6092 string operands, string constraints, list<dag> pattern>
6093 : I<outs, ins, asm, operands, constraints, pattern>,
6100 let Inst{28-21} = 0b01110000;
6107 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6108 RegisterOperand vecreg, RegisterClass regtype>
6109 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6110 "{\t$Rd" # size # ", $Rn" #
6111 "|" # size # "\t$Rd, $Rn}", "",
6112 [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6113 let Inst{20-16} = imm5;
6114 let Inst{14-11} = 0b0001;
6117 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6118 ValueType vectype, ValueType insreg,
6119 RegisterOperand vecreg, Operand idxtype,
6120 ValueType elttype, SDNode OpNode>
6121 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6122 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6123 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6124 [(set (vectype vecreg:$Rd),
6125 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6126 let Inst{14-11} = 0b0000;
6129 class SIMDDup64FromElement
6130 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6131 VectorIndexD, i64, AArch64duplane64> {
6134 let Inst{19-16} = 0b1000;
6137 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6138 RegisterOperand vecreg>
6139 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6140 VectorIndexS, i64, AArch64duplane32> {
6142 let Inst{20-19} = idx;
6143 let Inst{18-16} = 0b100;
6146 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6147 RegisterOperand vecreg>
6148 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6149 VectorIndexH, i64, AArch64duplane16> {
6151 let Inst{20-18} = idx;
6152 let Inst{17-16} = 0b10;
6155 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6156 RegisterOperand vecreg>
6157 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6158 VectorIndexB, i64, AArch64duplane8> {
6160 let Inst{20-17} = idx;
6164 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6165 Operand idxtype, string asm, list<dag> pattern>
6166 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6167 "{\t$Rd, $Rn" # size # "$idx" #
6168 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6169 let Inst{14-11} = imm4;
6172 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6174 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6175 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6177 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6178 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6180 class SIMDMovAlias<string asm, string size, Instruction inst,
6181 RegisterClass regtype, Operand idxtype>
6182 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6183 "|" # size # "\t$dst, $src$idx}",
6184 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6187 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6189 let Inst{20-17} = idx;
6192 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6194 let Inst{20-17} = idx;
6197 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6199 let Inst{20-18} = idx;
6200 let Inst{17-16} = 0b10;
6202 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6204 let Inst{20-18} = idx;
6205 let Inst{17-16} = 0b10;
6207 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6209 let Inst{20-19} = idx;
6210 let Inst{18-16} = 0b100;
6215 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6217 let Inst{20-17} = idx;
6220 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6222 let Inst{20-18} = idx;
6223 let Inst{17-16} = 0b10;
6225 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6227 let Inst{20-19} = idx;
6228 let Inst{18-16} = 0b100;
6230 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6233 let Inst{19-16} = 0b1000;
6235 def : SIMDMovAlias<"mov", ".s",
6236 !cast<Instruction>(NAME#"vi32"),
6237 GPR32, VectorIndexS>;
6238 def : SIMDMovAlias<"mov", ".d",
6239 !cast<Instruction>(NAME#"vi64"),
6240 GPR64, VectorIndexD>;
6243 class SIMDInsFromMain<string size, ValueType vectype,
6244 RegisterClass regtype, Operand idxtype>
6245 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6246 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6247 "{\t$Rd" # size # "$idx, $Rn" #
6248 "|" # size # "\t$Rd$idx, $Rn}",
6251 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6252 let Inst{14-11} = 0b0011;
6255 class SIMDInsFromElement<string size, ValueType vectype,
6256 ValueType elttype, Operand idxtype>
6257 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6258 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6259 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6260 "|" # size # "\t$Rd$idx, $Rn$idx2}",
6265 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6268 class SIMDInsMainMovAlias<string size, Instruction inst,
6269 RegisterClass regtype, Operand idxtype>
6270 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6271 "|" # size #"\t$dst$idx, $src}",
6272 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6273 class SIMDInsElementMovAlias<string size, Instruction inst,
6275 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6276 # "|" # size #"\t$dst$idx, $src$idx2}",
6277 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6280 multiclass SIMDIns {
6281 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6283 let Inst{20-17} = idx;
6286 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6288 let Inst{20-18} = idx;
6289 let Inst{17-16} = 0b10;
6291 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6293 let Inst{20-19} = idx;
6294 let Inst{18-16} = 0b100;
6296 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6299 let Inst{19-16} = 0b1000;
6302 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6305 let Inst{20-17} = idx;
6307 let Inst{14-11} = idx2;
6309 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6312 let Inst{20-18} = idx;
6313 let Inst{17-16} = 0b10;
6314 let Inst{14-12} = idx2;
6317 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6320 let Inst{20-19} = idx;
6321 let Inst{18-16} = 0b100;
6322 let Inst{14-13} = idx2;
6323 let Inst{12-11} = {?,?};
6325 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6329 let Inst{19-16} = 0b1000;
6330 let Inst{14} = idx2;
6331 let Inst{13-11} = {?,?,?};
6334 // For all forms of the INS instruction, the "mov" mnemonic is the
6335 // preferred alias. Why they didn't just call the instruction "mov" in
6336 // the first place is a very good question indeed...
6337 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6338 GPR32, VectorIndexB>;
6339 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6340 GPR32, VectorIndexH>;
6341 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6342 GPR32, VectorIndexS>;
6343 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6344 GPR64, VectorIndexD>;
6346 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6348 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6350 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6352 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6356 //----------------------------------------------------------------------------
6358 //----------------------------------------------------------------------------
6360 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6361 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6362 RegisterOperand listtype, string asm, string kind>
6363 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6364 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6371 let Inst{29-21} = 0b001110000;
6372 let Inst{20-16} = Vm;
6374 let Inst{14-13} = len;
6376 let Inst{11-10} = 0b00;
6381 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6382 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6383 RegisterOperand listtype, string asm, string kind>
6384 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6385 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6392 let Inst{29-21} = 0b001110000;
6393 let Inst{20-16} = Vm;
6395 let Inst{14-13} = len;
6397 let Inst{11-10} = 0b00;
6402 class SIMDTableLookupAlias<string asm, Instruction inst,
6403 RegisterOperand vectype, RegisterOperand listtype>
6404 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6405 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6407 multiclass SIMDTableLookup<bit op, string asm> {
6408 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6410 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6412 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6414 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6416 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6418 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6420 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6422 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6425 def : SIMDTableLookupAlias<asm # ".8b",
6426 !cast<Instruction>(NAME#"v8i8One"),
6427 V64, VecListOne128>;
6428 def : SIMDTableLookupAlias<asm # ".8b",
6429 !cast<Instruction>(NAME#"v8i8Two"),
6430 V64, VecListTwo128>;
6431 def : SIMDTableLookupAlias<asm # ".8b",
6432 !cast<Instruction>(NAME#"v8i8Three"),
6433 V64, VecListThree128>;
6434 def : SIMDTableLookupAlias<asm # ".8b",
6435 !cast<Instruction>(NAME#"v8i8Four"),
6436 V64, VecListFour128>;
6437 def : SIMDTableLookupAlias<asm # ".16b",
6438 !cast<Instruction>(NAME#"v16i8One"),
6439 V128, VecListOne128>;
6440 def : SIMDTableLookupAlias<asm # ".16b",
6441 !cast<Instruction>(NAME#"v16i8Two"),
6442 V128, VecListTwo128>;
6443 def : SIMDTableLookupAlias<asm # ".16b",
6444 !cast<Instruction>(NAME#"v16i8Three"),
6445 V128, VecListThree128>;
6446 def : SIMDTableLookupAlias<asm # ".16b",
6447 !cast<Instruction>(NAME#"v16i8Four"),
6448 V128, VecListFour128>;
6451 multiclass SIMDTableLookupTied<bit op, string asm> {
6452 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6454 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6456 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6458 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6460 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6462 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6464 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6466 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6469 def : SIMDTableLookupAlias<asm # ".8b",
6470 !cast<Instruction>(NAME#"v8i8One"),
6471 V64, VecListOne128>;
6472 def : SIMDTableLookupAlias<asm # ".8b",
6473 !cast<Instruction>(NAME#"v8i8Two"),
6474 V64, VecListTwo128>;
6475 def : SIMDTableLookupAlias<asm # ".8b",
6476 !cast<Instruction>(NAME#"v8i8Three"),
6477 V64, VecListThree128>;
6478 def : SIMDTableLookupAlias<asm # ".8b",
6479 !cast<Instruction>(NAME#"v8i8Four"),
6480 V64, VecListFour128>;
6481 def : SIMDTableLookupAlias<asm # ".16b",
6482 !cast<Instruction>(NAME#"v16i8One"),
6483 V128, VecListOne128>;
6484 def : SIMDTableLookupAlias<asm # ".16b",
6485 !cast<Instruction>(NAME#"v16i8Two"),
6486 V128, VecListTwo128>;
6487 def : SIMDTableLookupAlias<asm # ".16b",
6488 !cast<Instruction>(NAME#"v16i8Three"),
6489 V128, VecListThree128>;
6490 def : SIMDTableLookupAlias<asm # ".16b",
6491 !cast<Instruction>(NAME#"v16i8Four"),
6492 V128, VecListFour128>;
6496 //----------------------------------------------------------------------------
6497 // AdvSIMD scalar CPY
6498 //----------------------------------------------------------------------------
6499 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6500 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6501 string kind, Operand idxtype>
6502 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6503 "{\t$dst, $src" # kind # "$idx" #
6504 "|\t$dst, $src$idx}", "", []>,
6508 let Inst{31-21} = 0b01011110000;
6509 let Inst{15-10} = 0b000001;
6510 let Inst{9-5} = src;
6511 let Inst{4-0} = dst;
6514 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6515 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6516 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6517 # "|\t$dst, $src$index}",
6518 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6521 multiclass SIMDScalarCPY<string asm> {
6522 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
6524 let Inst{20-17} = idx;
6527 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6529 let Inst{20-18} = idx;
6530 let Inst{17-16} = 0b10;
6532 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6534 let Inst{20-19} = idx;
6535 let Inst{18-16} = 0b100;
6537 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6540 let Inst{19-16} = 0b1000;
6543 def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6544 VectorIndexD:$idx)))),
6545 (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6547 // 'DUP' mnemonic aliases.
6548 def : SIMDScalarCPYAlias<"dup", ".b",
6549 !cast<Instruction>(NAME#"i8"),
6550 FPR8, V128, VectorIndexB>;
6551 def : SIMDScalarCPYAlias<"dup", ".h",
6552 !cast<Instruction>(NAME#"i16"),
6553 FPR16, V128, VectorIndexH>;
6554 def : SIMDScalarCPYAlias<"dup", ".s",
6555 !cast<Instruction>(NAME#"i32"),
6556 FPR32, V128, VectorIndexS>;
6557 def : SIMDScalarCPYAlias<"dup", ".d",
6558 !cast<Instruction>(NAME#"i64"),
6559 FPR64, V128, VectorIndexD>;
6562 //----------------------------------------------------------------------------
6563 // AdvSIMD modified immediate instructions
6564 //----------------------------------------------------------------------------
6566 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
6567 string asm, string op_string,
6568 string cstr, list<dag> pattern>
6569 : I<oops, iops, asm, op_string, cstr, pattern>,
6576 let Inst{28-19} = 0b0111100000;
6577 let Inst{18-16} = imm8{7-5};
6580 let Inst{9-5} = imm8{4-0};
6584 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
6585 Operand immtype, dag opt_shift_iop,
6586 string opt_shift, string asm, string kind,
6588 : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
6589 !con((ins immtype:$imm8), opt_shift_iop), asm,
6590 "{\t$Rd" # kind # ", $imm8" # opt_shift #
6591 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6593 let DecoderMethod = "DecodeModImmInstruction";
6596 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6597 Operand immtype, dag opt_shift_iop,
6598 string opt_shift, string asm, string kind,
6600 : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
6601 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6602 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6603 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6604 "$Rd = $dst", pattern> {
6605 let DecoderMethod = "DecodeModImmTiedInstruction";
6608 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6609 RegisterOperand vectype, string asm,
6610 string kind, list<dag> pattern>
6611 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6612 (ins logical_vec_shift:$shift),
6613 "$shift", asm, kind, pattern> {
6615 let Inst{15} = b15_b12{1};
6616 let Inst{14-13} = shift;
6617 let Inst{12} = b15_b12{0};
6620 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6621 RegisterOperand vectype, string asm,
6622 string kind, list<dag> pattern>
6623 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6624 (ins logical_vec_shift:$shift),
6625 "$shift", asm, kind, pattern> {
6627 let Inst{15} = b15_b12{1};
6628 let Inst{14-13} = shift;
6629 let Inst{12} = b15_b12{0};
6633 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6634 RegisterOperand vectype, string asm,
6635 string kind, list<dag> pattern>
6636 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6637 (ins logical_vec_hw_shift:$shift),
6638 "$shift", asm, kind, pattern> {
6640 let Inst{15} = b15_b12{1};
6642 let Inst{13} = shift{0};
6643 let Inst{12} = b15_b12{0};
6646 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6647 RegisterOperand vectype, string asm,
6648 string kind, list<dag> pattern>
6649 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6650 (ins logical_vec_hw_shift:$shift),
6651 "$shift", asm, kind, pattern> {
6653 let Inst{15} = b15_b12{1};
6655 let Inst{13} = shift{0};
6656 let Inst{12} = b15_b12{0};
6659 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6661 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6663 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6666 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6668 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6672 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6673 bits<2> w_cmode, string asm,
6675 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6677 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6679 (i32 imm:$shift)))]>;
6680 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6682 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6684 (i32 imm:$shift)))]>;
6686 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6688 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6690 (i32 imm:$shift)))]>;
6691 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6693 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6695 (i32 imm:$shift)))]>;
6698 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6699 RegisterOperand vectype, string asm,
6700 string kind, list<dag> pattern>
6701 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6702 (ins move_vec_shift:$shift),
6703 "$shift", asm, kind, pattern> {
6705 let Inst{15-13} = cmode{3-1};
6706 let Inst{12} = shift;
6709 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
6710 RegisterOperand vectype,
6711 Operand imm_type, string asm,
6712 string kind, list<dag> pattern>
6713 : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
6714 asm, kind, pattern> {
6715 let Inst{15-12} = cmode;
6718 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6720 : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6721 "\t$Rd, $imm8", "", pattern> {
6722 let Inst{15-12} = cmode;
6723 let DecoderMethod = "DecodeModImmInstruction";
6726 //----------------------------------------------------------------------------
6727 // AdvSIMD indexed element
6728 //----------------------------------------------------------------------------
6730 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6731 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6732 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6733 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6734 string apple_kind, string dst_kind, string lhs_kind,
6735 string rhs_kind, list<dag> pattern>
6736 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6738 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6739 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6748 let Inst{28} = Scalar;
6749 let Inst{27-24} = 0b1111;
6750 let Inst{23-22} = size;
6751 // Bit 21 must be set by the derived class.
6752 let Inst{20-16} = Rm;
6753 let Inst{15-12} = opc;
6754 // Bit 11 must be set by the derived class.
6760 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6761 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6762 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6763 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6764 string apple_kind, string dst_kind, string lhs_kind,
6765 string rhs_kind, list<dag> pattern>
6766 : I<(outs dst_reg:$dst),
6767 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6768 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6769 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6778 let Inst{28} = Scalar;
6779 let Inst{27-24} = 0b1111;
6780 let Inst{23-22} = size;
6781 // Bit 21 must be set by the derived class.
6782 let Inst{20-16} = Rm;
6783 let Inst{15-12} = opc;
6784 // Bit 11 must be set by the derived class.
6790 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
6791 SDPatternOperator OpNode> {
6792 let Predicates = [HasNEON, HasFullFP16] in {
6793 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
6795 V128_lo, VectorIndexH,
6796 asm, ".4h", ".4h", ".4h", ".h",
6797 [(set (v4f16 V64:$Rd),
6798 (OpNode (v4f16 V64:$Rn),
6799 (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6801 let Inst{11} = idx{2};
6802 let Inst{21} = idx{1};
6803 let Inst{20} = idx{0};
6806 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
6808 V128_lo, VectorIndexH,
6809 asm, ".8h", ".8h", ".8h", ".h",
6810 [(set (v8f16 V128:$Rd),
6811 (OpNode (v8f16 V128:$Rn),
6812 (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6814 let Inst{11} = idx{2};
6815 let Inst{21} = idx{1};
6816 let Inst{20} = idx{0};
6818 } // Predicates = [HasNEON, HasFullFP16]
6820 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6823 asm, ".2s", ".2s", ".2s", ".s",
6824 [(set (v2f32 V64:$Rd),
6825 (OpNode (v2f32 V64:$Rn),
6826 (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6828 let Inst{11} = idx{1};
6829 let Inst{21} = idx{0};
6832 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6835 asm, ".4s", ".4s", ".4s", ".s",
6836 [(set (v4f32 V128:$Rd),
6837 (OpNode (v4f32 V128:$Rn),
6838 (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6840 let Inst{11} = idx{1};
6841 let Inst{21} = idx{0};
6844 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6847 asm, ".2d", ".2d", ".2d", ".d",
6848 [(set (v2f64 V128:$Rd),
6849 (OpNode (v2f64 V128:$Rn),
6850 (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6852 let Inst{11} = idx{0};
6856 let Predicates = [HasNEON, HasFullFP16] in {
6857 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
6858 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6859 asm, ".h", "", "", ".h",
6860 [(set (f16 FPR16Op:$Rd),
6861 (OpNode (f16 FPR16Op:$Rn),
6862 (f16 (vector_extract (v8f16 V128_lo:$Rm),
6863 VectorIndexH:$idx))))]> {
6865 let Inst{11} = idx{2};
6866 let Inst{21} = idx{1};
6867 let Inst{20} = idx{0};
6869 } // Predicates = [HasNEON, HasFullFP16]
6871 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6872 FPR32Op, FPR32Op, V128, VectorIndexS,
6873 asm, ".s", "", "", ".s",
6874 [(set (f32 FPR32Op:$Rd),
6875 (OpNode (f32 FPR32Op:$Rn),
6876 (f32 (vector_extract (v4f32 V128:$Rm),
6877 VectorIndexS:$idx))))]> {
6879 let Inst{11} = idx{1};
6880 let Inst{21} = idx{0};
6883 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6884 FPR64Op, FPR64Op, V128, VectorIndexD,
6885 asm, ".d", "", "", ".d",
6886 [(set (f64 FPR64Op:$Rd),
6887 (OpNode (f64 FPR64Op:$Rn),
6888 (f64 (vector_extract (v2f64 V128:$Rm),
6889 VectorIndexD:$idx))))]> {
6891 let Inst{11} = idx{0};
6896 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
6897 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6898 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6899 (AArch64duplane32 (v4f32 V128:$Rm),
6900 VectorIndexS:$idx))),
6901 (!cast<Instruction>(INST # v2i32_indexed)
6902 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6903 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6904 (AArch64dup (f32 FPR32Op:$Rm)))),
6905 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6906 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6909 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6910 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6911 (AArch64duplane32 (v4f32 V128:$Rm),
6912 VectorIndexS:$idx))),
6913 (!cast<Instruction>(INST # "v4i32_indexed")
6914 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6915 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6916 (AArch64dup (f32 FPR32Op:$Rm)))),
6917 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6918 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6920 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6921 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6922 (AArch64duplane64 (v2f64 V128:$Rm),
6923 VectorIndexD:$idx))),
6924 (!cast<Instruction>(INST # "v2i64_indexed")
6925 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6926 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6927 (AArch64dup (f64 FPR64Op:$Rm)))),
6928 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6929 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6931 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6932 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6933 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6934 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6935 V128:$Rm, VectorIndexS:$idx)>;
6936 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6937 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6938 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6939 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6941 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6942 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6943 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6944 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6945 V128:$Rm, VectorIndexD:$idx)>;
6948 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
6949 let Predicates = [HasNEON, HasFullFP16] in {
6950 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
6951 V128_lo, VectorIndexH,
6952 asm, ".4h", ".4h", ".4h", ".h", []> {
6954 let Inst{11} = idx{2};
6955 let Inst{21} = idx{1};
6956 let Inst{20} = idx{0};
6959 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
6961 V128_lo, VectorIndexH,
6962 asm, ".8h", ".8h", ".8h", ".h", []> {
6964 let Inst{11} = idx{2};
6965 let Inst{21} = idx{1};
6966 let Inst{20} = idx{0};
6968 } // Predicates = [HasNEON, HasFullFP16]
6970 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6972 asm, ".2s", ".2s", ".2s", ".s", []> {
6974 let Inst{11} = idx{1};
6975 let Inst{21} = idx{0};
6978 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6981 asm, ".4s", ".4s", ".4s", ".s", []> {
6983 let Inst{11} = idx{1};
6984 let Inst{21} = idx{0};
6987 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6990 asm, ".2d", ".2d", ".2d", ".d", []> {
6992 let Inst{11} = idx{0};
6996 let Predicates = [HasNEON, HasFullFP16] in {
6997 def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
6998 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6999 asm, ".h", "", "", ".h", []> {
7001 let Inst{11} = idx{2};
7002 let Inst{21} = idx{1};
7003 let Inst{20} = idx{0};
7005 } // Predicates = [HasNEON, HasFullFP16]
7007 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7008 FPR32Op, FPR32Op, V128, VectorIndexS,
7009 asm, ".s", "", "", ".s", []> {
7011 let Inst{11} = idx{1};
7012 let Inst{21} = idx{0};
7015 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7016 FPR64Op, FPR64Op, V128, VectorIndexD,
7017 asm, ".d", "", "", ".d", []> {
7019 let Inst{11} = idx{0};
7024 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7025 SDPatternOperator OpNode> {
7026 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7027 V128_lo, VectorIndexH,
7028 asm, ".4h", ".4h", ".4h", ".h",
7029 [(set (v4i16 V64:$Rd),
7030 (OpNode (v4i16 V64:$Rn),
7031 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7033 let Inst{11} = idx{2};
7034 let Inst{21} = idx{1};
7035 let Inst{20} = idx{0};
7038 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7040 V128_lo, VectorIndexH,
7041 asm, ".8h", ".8h", ".8h", ".h",
7042 [(set (v8i16 V128:$Rd),
7043 (OpNode (v8i16 V128:$Rn),
7044 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7046 let Inst{11} = idx{2};
7047 let Inst{21} = idx{1};
7048 let Inst{20} = idx{0};
7051 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7054 asm, ".2s", ".2s", ".2s", ".s",
7055 [(set (v2i32 V64:$Rd),
7056 (OpNode (v2i32 V64:$Rn),
7057 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7059 let Inst{11} = idx{1};
7060 let Inst{21} = idx{0};
7063 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7066 asm, ".4s", ".4s", ".4s", ".s",
7067 [(set (v4i32 V128:$Rd),
7068 (OpNode (v4i32 V128:$Rn),
7069 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7071 let Inst{11} = idx{1};
7072 let Inst{21} = idx{0};
7075 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7076 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7077 asm, ".h", "", "", ".h", []> {
7079 let Inst{11} = idx{2};
7080 let Inst{21} = idx{1};
7081 let Inst{20} = idx{0};
7084 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7085 FPR32Op, FPR32Op, V128, VectorIndexS,
7086 asm, ".s", "", "", ".s",
7087 [(set (i32 FPR32Op:$Rd),
7088 (OpNode FPR32Op:$Rn,
7089 (i32 (vector_extract (v4i32 V128:$Rm),
7090 VectorIndexS:$idx))))]> {
7092 let Inst{11} = idx{1};
7093 let Inst{21} = idx{0};
7097 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7098 SDPatternOperator OpNode> {
7099 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7101 V128_lo, VectorIndexH,
7102 asm, ".4h", ".4h", ".4h", ".h",
7103 [(set (v4i16 V64:$Rd),
7104 (OpNode (v4i16 V64:$Rn),
7105 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7107 let Inst{11} = idx{2};
7108 let Inst{21} = idx{1};
7109 let Inst{20} = idx{0};
7112 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7114 V128_lo, VectorIndexH,
7115 asm, ".8h", ".8h", ".8h", ".h",
7116 [(set (v8i16 V128:$Rd),
7117 (OpNode (v8i16 V128:$Rn),
7118 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7120 let Inst{11} = idx{2};
7121 let Inst{21} = idx{1};
7122 let Inst{20} = idx{0};
7125 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7128 asm, ".2s", ".2s", ".2s", ".s",
7129 [(set (v2i32 V64:$Rd),
7130 (OpNode (v2i32 V64:$Rn),
7131 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7133 let Inst{11} = idx{1};
7134 let Inst{21} = idx{0};
7137 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7140 asm, ".4s", ".4s", ".4s", ".s",
7141 [(set (v4i32 V128:$Rd),
7142 (OpNode (v4i32 V128:$Rn),
7143 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7145 let Inst{11} = idx{1};
7146 let Inst{21} = idx{0};
7150 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7151 SDPatternOperator OpNode> {
7152 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7153 V128_lo, VectorIndexH,
7154 asm, ".4h", ".4h", ".4h", ".h",
7155 [(set (v4i16 V64:$dst),
7156 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7157 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7159 let Inst{11} = idx{2};
7160 let Inst{21} = idx{1};
7161 let Inst{20} = idx{0};
7164 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7166 V128_lo, VectorIndexH,
7167 asm, ".8h", ".8h", ".8h", ".h",
7168 [(set (v8i16 V128:$dst),
7169 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7170 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7172 let Inst{11} = idx{2};
7173 let Inst{21} = idx{1};
7174 let Inst{20} = idx{0};
7177 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7180 asm, ".2s", ".2s", ".2s", ".s",
7181 [(set (v2i32 V64:$dst),
7182 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7183 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7185 let Inst{11} = idx{1};
7186 let Inst{21} = idx{0};
7189 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7192 asm, ".4s", ".4s", ".4s", ".s",
7193 [(set (v4i32 V128:$dst),
7194 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7195 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7197 let Inst{11} = idx{1};
7198 let Inst{21} = idx{0};
7202 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7203 SDPatternOperator OpNode> {
7204 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7206 V128_lo, VectorIndexH,
7207 asm, ".4s", ".4s", ".4h", ".h",
7208 [(set (v4i32 V128:$Rd),
7209 (OpNode (v4i16 V64:$Rn),
7210 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7212 let Inst{11} = idx{2};
7213 let Inst{21} = idx{1};
7214 let Inst{20} = idx{0};
7217 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7219 V128_lo, VectorIndexH,
7220 asm#"2", ".4s", ".4s", ".8h", ".h",
7221 [(set (v4i32 V128:$Rd),
7222 (OpNode (extract_high_v8i16 V128:$Rn),
7223 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7224 VectorIndexH:$idx))))]> {
7227 let Inst{11} = idx{2};
7228 let Inst{21} = idx{1};
7229 let Inst{20} = idx{0};
7232 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7235 asm, ".2d", ".2d", ".2s", ".s",
7236 [(set (v2i64 V128:$Rd),
7237 (OpNode (v2i32 V64:$Rn),
7238 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7240 let Inst{11} = idx{1};
7241 let Inst{21} = idx{0};
7244 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7247 asm#"2", ".2d", ".2d", ".4s", ".s",
7248 [(set (v2i64 V128:$Rd),
7249 (OpNode (extract_high_v4i32 V128:$Rn),
7250 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7251 VectorIndexS:$idx))))]> {
7253 let Inst{11} = idx{1};
7254 let Inst{21} = idx{0};
7257 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7258 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7259 asm, ".h", "", "", ".h", []> {
7261 let Inst{11} = idx{2};
7262 let Inst{21} = idx{1};
7263 let Inst{20} = idx{0};
7266 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7267 FPR64Op, FPR32Op, V128, VectorIndexS,
7268 asm, ".s", "", "", ".s", []> {
7270 let Inst{11} = idx{1};
7271 let Inst{21} = idx{0};
7275 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7276 SDPatternOperator Accum> {
7277 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7279 V128_lo, VectorIndexH,
7280 asm, ".4s", ".4s", ".4h", ".h",
7281 [(set (v4i32 V128:$dst),
7282 (Accum (v4i32 V128:$Rd),
7283 (v4i32 (int_aarch64_neon_sqdmull
7285 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7286 VectorIndexH:$idx))))))]> {
7288 let Inst{11} = idx{2};
7289 let Inst{21} = idx{1};
7290 let Inst{20} = idx{0};
7293 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7294 // intermediate EXTRACT_SUBREG would be untyped.
7295 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7296 (i32 (vector_extract (v4i32
7297 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7298 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7299 VectorIndexH:$idx)))),
7302 (!cast<Instruction>(NAME # v4i16_indexed)
7303 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7304 V128_lo:$Rm, VectorIndexH:$idx),
7307 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7309 V128_lo, VectorIndexH,
7310 asm#"2", ".4s", ".4s", ".8h", ".h",
7311 [(set (v4i32 V128:$dst),
7312 (Accum (v4i32 V128:$Rd),
7313 (v4i32 (int_aarch64_neon_sqdmull
7314 (extract_high_v8i16 V128:$Rn),
7316 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7317 VectorIndexH:$idx))))))]> {
7319 let Inst{11} = idx{2};
7320 let Inst{21} = idx{1};
7321 let Inst{20} = idx{0};
7324 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7327 asm, ".2d", ".2d", ".2s", ".s",
7328 [(set (v2i64 V128:$dst),
7329 (Accum (v2i64 V128:$Rd),
7330 (v2i64 (int_aarch64_neon_sqdmull
7332 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7333 VectorIndexS:$idx))))))]> {
7335 let Inst{11} = idx{1};
7336 let Inst{21} = idx{0};
7339 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7342 asm#"2", ".2d", ".2d", ".4s", ".s",
7343 [(set (v2i64 V128:$dst),
7344 (Accum (v2i64 V128:$Rd),
7345 (v2i64 (int_aarch64_neon_sqdmull
7346 (extract_high_v4i32 V128:$Rn),
7348 (AArch64duplane32 (v4i32 V128:$Rm),
7349 VectorIndexS:$idx))))))]> {
7351 let Inst{11} = idx{1};
7352 let Inst{21} = idx{0};
7355 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7356 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7357 asm, ".h", "", "", ".h", []> {
7359 let Inst{11} = idx{2};
7360 let Inst{21} = idx{1};
7361 let Inst{20} = idx{0};
7365 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7366 FPR64Op, FPR32Op, V128, VectorIndexS,
7367 asm, ".s", "", "", ".s",
7368 [(set (i64 FPR64Op:$dst),
7369 (Accum (i64 FPR64Op:$Rd),
7370 (i64 (int_aarch64_neon_sqdmulls_scalar
7372 (i32 (vector_extract (v4i32 V128:$Rm),
7373 VectorIndexS:$idx))))))]> {
7376 let Inst{11} = idx{1};
7377 let Inst{21} = idx{0};
7381 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7382 SDPatternOperator OpNode> {
7383 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7384 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7386 V128_lo, VectorIndexH,
7387 asm, ".4s", ".4s", ".4h", ".h",
7388 [(set (v4i32 V128:$Rd),
7389 (OpNode (v4i16 V64:$Rn),
7390 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7392 let Inst{11} = idx{2};
7393 let Inst{21} = idx{1};
7394 let Inst{20} = idx{0};
7397 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7399 V128_lo, VectorIndexH,
7400 asm#"2", ".4s", ".4s", ".8h", ".h",
7401 [(set (v4i32 V128:$Rd),
7402 (OpNode (extract_high_v8i16 V128:$Rn),
7403 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7404 VectorIndexH:$idx))))]> {
7407 let Inst{11} = idx{2};
7408 let Inst{21} = idx{1};
7409 let Inst{20} = idx{0};
7412 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7415 asm, ".2d", ".2d", ".2s", ".s",
7416 [(set (v2i64 V128:$Rd),
7417 (OpNode (v2i32 V64:$Rn),
7418 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7420 let Inst{11} = idx{1};
7421 let Inst{21} = idx{0};
7424 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7427 asm#"2", ".2d", ".2d", ".4s", ".s",
7428 [(set (v2i64 V128:$Rd),
7429 (OpNode (extract_high_v4i32 V128:$Rn),
7430 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7431 VectorIndexS:$idx))))]> {
7433 let Inst{11} = idx{1};
7434 let Inst{21} = idx{0};
7439 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7440 SDPatternOperator OpNode> {
7441 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7442 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7444 V128_lo, VectorIndexH,
7445 asm, ".4s", ".4s", ".4h", ".h",
7446 [(set (v4i32 V128:$dst),
7447 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7448 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7450 let Inst{11} = idx{2};
7451 let Inst{21} = idx{1};
7452 let Inst{20} = idx{0};
7455 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7457 V128_lo, VectorIndexH,
7458 asm#"2", ".4s", ".4s", ".8h", ".h",
7459 [(set (v4i32 V128:$dst),
7460 (OpNode (v4i32 V128:$Rd),
7461 (extract_high_v8i16 V128:$Rn),
7462 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7463 VectorIndexH:$idx))))]> {
7465 let Inst{11} = idx{2};
7466 let Inst{21} = idx{1};
7467 let Inst{20} = idx{0};
7470 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7473 asm, ".2d", ".2d", ".2s", ".s",
7474 [(set (v2i64 V128:$dst),
7475 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7476 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7478 let Inst{11} = idx{1};
7479 let Inst{21} = idx{0};
7482 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7485 asm#"2", ".2d", ".2d", ".4s", ".s",
7486 [(set (v2i64 V128:$dst),
7487 (OpNode (v2i64 V128:$Rd),
7488 (extract_high_v4i32 V128:$Rn),
7489 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7490 VectorIndexS:$idx))))]> {
7492 let Inst{11} = idx{1};
7493 let Inst{21} = idx{0};
7498 //----------------------------------------------------------------------------
7499 // AdvSIMD scalar shift by immediate
7500 //----------------------------------------------------------------------------
7502 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7503 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7504 RegisterClass regtype1, RegisterClass regtype2,
7505 Operand immtype, string asm, list<dag> pattern>
7506 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7507 asm, "\t$Rd, $Rn, $imm", "", pattern>,
7512 let Inst{31-30} = 0b01;
7514 let Inst{28-23} = 0b111110;
7515 let Inst{22-16} = fixed_imm;
7516 let Inst{15-11} = opc;
7522 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7523 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7524 RegisterClass regtype1, RegisterClass regtype2,
7525 Operand immtype, string asm, list<dag> pattern>
7526 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7527 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7532 let Inst{31-30} = 0b01;
7534 let Inst{28-23} = 0b111110;
7535 let Inst{22-16} = fixed_imm;
7536 let Inst{15-11} = opc;
7543 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
7544 let Predicates = [HasNEON, HasFullFP16] in {
7545 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7546 FPR16, FPR16, vecshiftR16, asm, []> {
7547 let Inst{19-16} = imm{3-0};
7549 } // Predicates = [HasNEON, HasFullFP16]
7550 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7551 FPR32, FPR32, vecshiftR32, asm, []> {
7552 let Inst{20-16} = imm{4-0};
7555 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7556 FPR64, FPR64, vecshiftR64, asm, []> {
7557 let Inst{21-16} = imm{5-0};
7561 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7562 SDPatternOperator OpNode> {
7563 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7564 FPR64, FPR64, vecshiftR64, asm,
7565 [(set (i64 FPR64:$Rd),
7566 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7567 let Inst{21-16} = imm{5-0};
7570 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7571 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7574 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7575 SDPatternOperator OpNode = null_frag> {
7576 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7577 FPR64, FPR64, vecshiftR64, asm,
7578 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7579 (i32 vecshiftR64:$imm)))]> {
7580 let Inst{21-16} = imm{5-0};
7583 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7584 (i32 vecshiftR64:$imm))),
7585 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7589 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7590 SDPatternOperator OpNode> {
7591 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7592 FPR64, FPR64, vecshiftL64, asm,
7593 [(set (v1i64 FPR64:$Rd),
7594 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7595 let Inst{21-16} = imm{5-0};
7599 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7600 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7601 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7602 FPR64, FPR64, vecshiftL64, asm, []> {
7603 let Inst{21-16} = imm{5-0};
7607 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7608 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7609 SDPatternOperator OpNode = null_frag> {
7610 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7611 FPR8, FPR16, vecshiftR8, asm, []> {
7612 let Inst{18-16} = imm{2-0};
7615 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7616 FPR16, FPR32, vecshiftR16, asm, []> {
7617 let Inst{19-16} = imm{3-0};
7620 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7621 FPR32, FPR64, vecshiftR32, asm,
7622 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7623 let Inst{20-16} = imm{4-0};
7627 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7628 SDPatternOperator OpNode> {
7629 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7630 FPR8, FPR8, vecshiftL8, asm, []> {
7631 let Inst{18-16} = imm{2-0};
7634 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7635 FPR16, FPR16, vecshiftL16, asm, []> {
7636 let Inst{19-16} = imm{3-0};
7639 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7640 FPR32, FPR32, vecshiftL32, asm,
7641 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7642 let Inst{20-16} = imm{4-0};
7645 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7646 FPR64, FPR64, vecshiftL64, asm,
7647 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7648 let Inst{21-16} = imm{5-0};
7651 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7652 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7655 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7656 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7657 FPR8, FPR8, vecshiftR8, asm, []> {
7658 let Inst{18-16} = imm{2-0};
7661 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7662 FPR16, FPR16, vecshiftR16, asm, []> {
7663 let Inst{19-16} = imm{3-0};
7666 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7667 FPR32, FPR32, vecshiftR32, asm, []> {
7668 let Inst{20-16} = imm{4-0};
7671 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7672 FPR64, FPR64, vecshiftR64, asm, []> {
7673 let Inst{21-16} = imm{5-0};
7677 //----------------------------------------------------------------------------
7678 // AdvSIMD vector x indexed element
7679 //----------------------------------------------------------------------------
7681 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7682 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7683 RegisterOperand dst_reg, RegisterOperand src_reg,
7685 string asm, string dst_kind, string src_kind,
7687 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7688 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7689 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7696 let Inst{28-23} = 0b011110;
7697 let Inst{22-16} = fixed_imm;
7698 let Inst{15-11} = opc;
7704 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7705 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7706 RegisterOperand vectype1, RegisterOperand vectype2,
7708 string asm, string dst_kind, string src_kind,
7710 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7711 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7712 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7719 let Inst{28-23} = 0b011110;
7720 let Inst{22-16} = fixed_imm;
7721 let Inst{15-11} = opc;
7727 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7729 let Predicates = [HasNEON, HasFullFP16] in {
7730 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7731 V64, V64, vecshiftR16,
7733 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
7735 let Inst{19-16} = imm;
7738 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7739 V128, V128, vecshiftR16,
7741 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
7743 let Inst{19-16} = imm;
7745 } // Predicates = [HasNEON, HasFullFP16]
7746 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7747 V64, V64, vecshiftR32,
7749 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7751 let Inst{20-16} = imm;
7754 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7755 V128, V128, vecshiftR32,
7757 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7759 let Inst{20-16} = imm;
7762 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7763 V128, V128, vecshiftR64,
7765 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7767 let Inst{21-16} = imm;
7771 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
7773 let Predicates = [HasNEON, HasFullFP16] in {
7774 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7775 V64, V64, vecshiftR16,
7777 [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
7779 let Inst{19-16} = imm;
7782 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7783 V128, V128, vecshiftR16,
7785 [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
7787 let Inst{19-16} = imm;
7789 } // Predicates = [HasNEON, HasFullFP16]
7791 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7792 V64, V64, vecshiftR32,
7794 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7796 let Inst{20-16} = imm;
7799 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7800 V128, V128, vecshiftR32,
7802 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7804 let Inst{20-16} = imm;
7807 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7808 V128, V128, vecshiftR64,
7810 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7812 let Inst{21-16} = imm;
7816 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7817 SDPatternOperator OpNode> {
7818 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7819 V64, V128, vecshiftR16Narrow,
7821 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7823 let Inst{18-16} = imm;
7826 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7827 V128, V128, vecshiftR16Narrow,
7828 asm#"2", ".16b", ".8h", []> {
7830 let Inst{18-16} = imm;
7831 let hasSideEffects = 0;
7834 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7835 V64, V128, vecshiftR32Narrow,
7837 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7839 let Inst{19-16} = imm;
7842 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7843 V128, V128, vecshiftR32Narrow,
7844 asm#"2", ".8h", ".4s", []> {
7846 let Inst{19-16} = imm;
7847 let hasSideEffects = 0;
7850 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7851 V64, V128, vecshiftR64Narrow,
7853 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7855 let Inst{20-16} = imm;
7858 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7859 V128, V128, vecshiftR64Narrow,
7860 asm#"2", ".4s", ".2d", []> {
7862 let Inst{20-16} = imm;
7863 let hasSideEffects = 0;
7866 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7867 // themselves, so put them here instead.
7869 // Patterns involving what's effectively an insert high and a normal
7870 // intrinsic, represented by CONCAT_VECTORS.
7871 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7872 vecshiftR16Narrow:$imm)),
7873 (!cast<Instruction>(NAME # "v16i8_shift")
7874 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7875 V128:$Rn, vecshiftR16Narrow:$imm)>;
7876 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7877 vecshiftR32Narrow:$imm)),
7878 (!cast<Instruction>(NAME # "v8i16_shift")
7879 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7880 V128:$Rn, vecshiftR32Narrow:$imm)>;
7881 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7882 vecshiftR64Narrow:$imm)),
7883 (!cast<Instruction>(NAME # "v4i32_shift")
7884 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7885 V128:$Rn, vecshiftR64Narrow:$imm)>;
7888 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7889 SDPatternOperator OpNode> {
7890 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7891 V64, V64, vecshiftL8,
7893 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7894 (i32 vecshiftL8:$imm)))]> {
7896 let Inst{18-16} = imm;
7899 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7900 V128, V128, vecshiftL8,
7901 asm, ".16b", ".16b",
7902 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7903 (i32 vecshiftL8:$imm)))]> {
7905 let Inst{18-16} = imm;
7908 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7909 V64, V64, vecshiftL16,
7911 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7912 (i32 vecshiftL16:$imm)))]> {
7914 let Inst{19-16} = imm;
7917 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7918 V128, V128, vecshiftL16,
7920 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7921 (i32 vecshiftL16:$imm)))]> {
7923 let Inst{19-16} = imm;
7926 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7927 V64, V64, vecshiftL32,
7929 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7930 (i32 vecshiftL32:$imm)))]> {
7932 let Inst{20-16} = imm;
7935 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7936 V128, V128, vecshiftL32,
7938 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7939 (i32 vecshiftL32:$imm)))]> {
7941 let Inst{20-16} = imm;
7944 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7945 V128, V128, vecshiftL64,
7947 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7948 (i32 vecshiftL64:$imm)))]> {
7950 let Inst{21-16} = imm;
7954 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7955 SDPatternOperator OpNode> {
7956 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7957 V64, V64, vecshiftR8,
7959 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7960 (i32 vecshiftR8:$imm)))]> {
7962 let Inst{18-16} = imm;
7965 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7966 V128, V128, vecshiftR8,
7967 asm, ".16b", ".16b",
7968 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7969 (i32 vecshiftR8:$imm)))]> {
7971 let Inst{18-16} = imm;
7974 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7975 V64, V64, vecshiftR16,
7977 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7978 (i32 vecshiftR16:$imm)))]> {
7980 let Inst{19-16} = imm;
7983 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7984 V128, V128, vecshiftR16,
7986 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7987 (i32 vecshiftR16:$imm)))]> {
7989 let Inst{19-16} = imm;
7992 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7993 V64, V64, vecshiftR32,
7995 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7996 (i32 vecshiftR32:$imm)))]> {
7998 let Inst{20-16} = imm;
8001 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8002 V128, V128, vecshiftR32,
8004 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8005 (i32 vecshiftR32:$imm)))]> {
8007 let Inst{20-16} = imm;
8010 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8011 V128, V128, vecshiftR64,
8013 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8014 (i32 vecshiftR64:$imm)))]> {
8016 let Inst{21-16} = imm;
8020 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8021 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8022 SDPatternOperator OpNode = null_frag> {
8023 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8024 V64, V64, vecshiftR8, asm, ".8b", ".8b",
8025 [(set (v8i8 V64:$dst),
8026 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8027 (i32 vecshiftR8:$imm)))]> {
8029 let Inst{18-16} = imm;
8032 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8033 V128, V128, vecshiftR8, asm, ".16b", ".16b",
8034 [(set (v16i8 V128:$dst),
8035 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8036 (i32 vecshiftR8:$imm)))]> {
8038 let Inst{18-16} = imm;
8041 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8042 V64, V64, vecshiftR16, asm, ".4h", ".4h",
8043 [(set (v4i16 V64:$dst),
8044 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8045 (i32 vecshiftR16:$imm)))]> {
8047 let Inst{19-16} = imm;
8050 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8051 V128, V128, vecshiftR16, asm, ".8h", ".8h",
8052 [(set (v8i16 V128:$dst),
8053 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8054 (i32 vecshiftR16:$imm)))]> {
8056 let Inst{19-16} = imm;
8059 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8060 V64, V64, vecshiftR32, asm, ".2s", ".2s",
8061 [(set (v2i32 V64:$dst),
8062 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8063 (i32 vecshiftR32:$imm)))]> {
8065 let Inst{20-16} = imm;
8068 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8069 V128, V128, vecshiftR32, asm, ".4s", ".4s",
8070 [(set (v4i32 V128:$dst),
8071 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8072 (i32 vecshiftR32:$imm)))]> {
8074 let Inst{20-16} = imm;
8077 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8078 V128, V128, vecshiftR64,
8079 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8080 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8081 (i32 vecshiftR64:$imm)))]> {
8083 let Inst{21-16} = imm;
8087 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8088 SDPatternOperator OpNode = null_frag> {
8089 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8090 V64, V64, vecshiftL8,
8092 [(set (v8i8 V64:$dst),
8093 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8094 (i32 vecshiftL8:$imm)))]> {
8096 let Inst{18-16} = imm;
8099 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8100 V128, V128, vecshiftL8,
8101 asm, ".16b", ".16b",
8102 [(set (v16i8 V128:$dst),
8103 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8104 (i32 vecshiftL8:$imm)))]> {
8106 let Inst{18-16} = imm;
8109 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8110 V64, V64, vecshiftL16,
8112 [(set (v4i16 V64:$dst),
8113 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8114 (i32 vecshiftL16:$imm)))]> {
8116 let Inst{19-16} = imm;
8119 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8120 V128, V128, vecshiftL16,
8122 [(set (v8i16 V128:$dst),
8123 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8124 (i32 vecshiftL16:$imm)))]> {
8126 let Inst{19-16} = imm;
8129 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8130 V64, V64, vecshiftL32,
8132 [(set (v2i32 V64:$dst),
8133 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8134 (i32 vecshiftL32:$imm)))]> {
8136 let Inst{20-16} = imm;
8139 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8140 V128, V128, vecshiftL32,
8142 [(set (v4i32 V128:$dst),
8143 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8144 (i32 vecshiftL32:$imm)))]> {
8146 let Inst{20-16} = imm;
8149 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8150 V128, V128, vecshiftL64,
8152 [(set (v2i64 V128:$dst),
8153 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8154 (i32 vecshiftL64:$imm)))]> {
8156 let Inst{21-16} = imm;
8160 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8161 SDPatternOperator OpNode> {
8162 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8163 V128, V64, vecshiftL8, asm, ".8h", ".8b",
8164 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8166 let Inst{18-16} = imm;
8169 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8170 V128, V128, vecshiftL8,
8171 asm#"2", ".8h", ".16b",
8172 [(set (v8i16 V128:$Rd),
8173 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8175 let Inst{18-16} = imm;
8178 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8179 V128, V64, vecshiftL16, asm, ".4s", ".4h",
8180 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8182 let Inst{19-16} = imm;
8185 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8186 V128, V128, vecshiftL16,
8187 asm#"2", ".4s", ".8h",
8188 [(set (v4i32 V128:$Rd),
8189 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8192 let Inst{19-16} = imm;
8195 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8196 V128, V64, vecshiftL32, asm, ".2d", ".2s",
8197 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8199 let Inst{20-16} = imm;
8202 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8203 V128, V128, vecshiftL32,
8204 asm#"2", ".2d", ".4s",
8205 [(set (v2i64 V128:$Rd),
8206 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8208 let Inst{20-16} = imm;
8214 // Vector load/store
8216 // SIMD ldX/stX no-index memory references don't allow the optional
8217 // ", #0" constant and handle post-indexing explicitly, so we use
8218 // a more specialized parse method for them. Otherwise, it's the same as
8219 // the general GPR64sp handling.
8221 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8222 string asm, dag oops, dag iops, list<dag> pattern>
8223 : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8228 let Inst{29-23} = 0b0011000;
8230 let Inst{21-16} = 0b000000;
8231 let Inst{15-12} = opcode;
8232 let Inst{11-10} = size;
8237 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8238 string asm, dag oops, dag iops>
8239 : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8245 let Inst{29-23} = 0b0011001;
8248 let Inst{20-16} = Xm;
8249 let Inst{15-12} = opcode;
8250 let Inst{11-10} = size;
8255 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8256 // register post-index addressing from the zero register.
8257 multiclass SIMDLdStAliases<string asm, string layout, string Count,
8258 int Offset, int Size> {
8259 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8260 // "ld1\t$Vt, [$Rn], #16"
8261 // may get mapped to
8262 // (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8263 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8264 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8266 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8269 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8270 // "ld1.8b\t$Vt, [$Rn], #16"
8271 // may get mapped to
8272 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8273 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8274 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8276 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8279 // E.g. "ld1.8b { v0, v1 }, [x1]"
8280 // "ld1\t$Vt, [$Rn]"
8281 // may get mapped to
8282 // (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8283 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8284 (!cast<Instruction>(NAME # Count # "v" # layout)
8285 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8288 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8289 // "ld1\t$Vt, [$Rn], $Xm"
8290 // may get mapped to
8291 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8292 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8293 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8295 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8296 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8299 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
8300 int Offset64, bits<4> opcode> {
8301 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8302 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8303 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8304 (ins GPR64sp:$Rn), []>;
8305 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8306 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8307 (ins GPR64sp:$Rn), []>;
8308 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8309 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8310 (ins GPR64sp:$Rn), []>;
8311 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8312 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8313 (ins GPR64sp:$Rn), []>;
8314 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8315 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8316 (ins GPR64sp:$Rn), []>;
8317 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8318 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8319 (ins GPR64sp:$Rn), []>;
8320 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8321 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8322 (ins GPR64sp:$Rn), []>;
8325 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8326 (outs GPR64sp:$wback,
8327 !cast<RegisterOperand>(veclist # "16b"):$Vt),
8329 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8330 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8331 (outs GPR64sp:$wback,
8332 !cast<RegisterOperand>(veclist # "8h"):$Vt),
8334 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8335 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8336 (outs GPR64sp:$wback,
8337 !cast<RegisterOperand>(veclist # "4s"):$Vt),
8339 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8340 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8341 (outs GPR64sp:$wback,
8342 !cast<RegisterOperand>(veclist # "2d"):$Vt),
8344 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8345 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8346 (outs GPR64sp:$wback,
8347 !cast<RegisterOperand>(veclist # "8b"):$Vt),
8349 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8350 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8351 (outs GPR64sp:$wback,
8352 !cast<RegisterOperand>(veclist # "4h"):$Vt),
8354 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8355 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8356 (outs GPR64sp:$wback,
8357 !cast<RegisterOperand>(veclist # "2s"):$Vt),
8359 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8362 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8363 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8364 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8365 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8366 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8367 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8368 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8371 // Only ld1/st1 has a v1d version.
8372 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
8373 int Offset64, bits<4> opcode> {
8374 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8375 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8376 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8378 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8379 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8381 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8382 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8384 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8385 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8387 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8388 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8390 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8391 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8393 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8394 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8397 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8398 (outs GPR64sp:$wback),
8399 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8401 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8402 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8403 (outs GPR64sp:$wback),
8404 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8406 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8407 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8408 (outs GPR64sp:$wback),
8409 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8411 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8412 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8413 (outs GPR64sp:$wback),
8414 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8416 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8417 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8418 (outs GPR64sp:$wback),
8419 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8421 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8422 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8423 (outs GPR64sp:$wback),
8424 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8426 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8427 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8428 (outs GPR64sp:$wback),
8429 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8431 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8434 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8435 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8436 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8437 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8438 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8439 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8440 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8443 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8444 int Offset128, int Offset64, bits<4> opcode>
8445 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8447 // LD1 instructions have extra "1d" variants.
8448 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8449 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8450 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8451 (ins GPR64sp:$Rn), []>;
8453 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8454 (outs GPR64sp:$wback,
8455 !cast<RegisterOperand>(veclist # "1d"):$Vt),
8457 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8460 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8463 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8464 int Offset128, int Offset64, bits<4> opcode>
8465 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8467 // ST1 instructions have extra "1d" variants.
8468 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8469 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8470 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8473 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8474 (outs GPR64sp:$wback),
8475 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8477 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8480 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8483 multiclass SIMDLd1Multiple<string asm> {
8484 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
8485 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8486 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8487 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8490 multiclass SIMDSt1Multiple<string asm> {
8491 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
8492 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8493 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8494 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8497 multiclass SIMDLd2Multiple<string asm> {
8498 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8501 multiclass SIMDSt2Multiple<string asm> {
8502 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8505 multiclass SIMDLd3Multiple<string asm> {
8506 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8509 multiclass SIMDSt3Multiple<string asm> {
8510 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8513 multiclass SIMDLd4Multiple<string asm> {
8514 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8517 multiclass SIMDSt4Multiple<string asm> {
8518 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8522 // AdvSIMD Load/store single-element
8525 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8526 string asm, string operands, string cst,
8527 dag oops, dag iops, list<dag> pattern>
8528 : I<oops, iops, asm, operands, cst, pattern> {
8532 let Inst{29-24} = 0b001101;
8535 let Inst{15-13} = opcode;
8540 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8541 string asm, string operands, string cst,
8542 dag oops, dag iops, list<dag> pattern>
8543 : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8547 let Inst{29-24} = 0b001101;
8550 let Inst{15-13} = opcode;
8556 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8557 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8559 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8560 (outs listtype:$Vt), (ins GPR64sp:$Rn),
8564 let Inst{20-16} = 0b00000;
8566 let Inst{11-10} = size;
8568 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8569 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8570 string asm, Operand listtype, Operand GPR64pi>
8571 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8573 (outs GPR64sp:$wback, listtype:$Vt),
8574 (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8578 let Inst{20-16} = Xm;
8580 let Inst{11-10} = size;
8583 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8584 int Offset, int Size> {
8585 // E.g. "ld1r { v0.8b }, [x1], #1"
8586 // "ld1r.8b\t$Vt, [$Rn], #1"
8587 // may get mapped to
8588 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8589 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8590 (!cast<Instruction>(NAME # "v" # layout # "_POST")
8592 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8595 // E.g. "ld1r.8b { v0 }, [x1], #1"
8596 // "ld1r.8b\t$Vt, [$Rn], #1"
8597 // may get mapped to
8598 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8599 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8600 (!cast<Instruction>(NAME # "v" # layout # "_POST")
8602 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8605 // E.g. "ld1r.8b { v0 }, [x1]"
8606 // "ld1r.8b\t$Vt, [$Rn]"
8607 // may get mapped to
8608 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8609 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8610 (!cast<Instruction>(NAME # "v" # layout)
8611 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8614 // E.g. "ld1r.8b { v0 }, [x1], x2"
8615 // "ld1r.8b\t$Vt, [$Rn], $Xm"
8616 // may get mapped to
8617 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8618 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8619 (!cast<Instruction>(NAME # "v" # layout # "_POST")
8621 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8622 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8625 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8626 int Offset1, int Offset2, int Offset4, int Offset8> {
8627 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8628 !cast<Operand>("VecList" # Count # "8b")>;
8629 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8630 !cast<Operand>("VecList" # Count #"16b")>;
8631 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8632 !cast<Operand>("VecList" # Count #"4h")>;
8633 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8634 !cast<Operand>("VecList" # Count #"8h")>;
8635 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8636 !cast<Operand>("VecList" # Count #"2s")>;
8637 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8638 !cast<Operand>("VecList" # Count #"4s")>;
8639 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8640 !cast<Operand>("VecList" # Count #"1d")>;
8641 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8642 !cast<Operand>("VecList" # Count #"2d")>;
8644 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8645 !cast<Operand>("VecList" # Count # "8b"),
8646 !cast<Operand>("GPR64pi" # Offset1)>;
8647 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8648 !cast<Operand>("VecList" # Count # "16b"),
8649 !cast<Operand>("GPR64pi" # Offset1)>;
8650 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8651 !cast<Operand>("VecList" # Count # "4h"),
8652 !cast<Operand>("GPR64pi" # Offset2)>;
8653 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8654 !cast<Operand>("VecList" # Count # "8h"),
8655 !cast<Operand>("GPR64pi" # Offset2)>;
8656 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8657 !cast<Operand>("VecList" # Count # "2s"),
8658 !cast<Operand>("GPR64pi" # Offset4)>;
8659 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8660 !cast<Operand>("VecList" # Count # "4s"),
8661 !cast<Operand>("GPR64pi" # Offset4)>;
8662 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8663 !cast<Operand>("VecList" # Count # "1d"),
8664 !cast<Operand>("GPR64pi" # Offset8)>;
8665 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8666 !cast<Operand>("VecList" # Count # "2d"),
8667 !cast<Operand>("GPR64pi" # Offset8)>;
8669 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
8670 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8671 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
8672 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
8673 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
8674 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
8675 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
8676 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
8679 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8680 dag oops, dag iops, list<dag> pattern>
8681 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8683 // idx encoded in Q:S:size fields.
8685 let Inst{30} = idx{3};
8687 let Inst{20-16} = 0b00000;
8688 let Inst{12} = idx{2};
8689 let Inst{11-10} = idx{1-0};
8691 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8692 dag oops, dag iops, list<dag> pattern>
8693 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8694 oops, iops, pattern> {
8695 // idx encoded in Q:S:size fields.
8697 let Inst{30} = idx{3};
8699 let Inst{20-16} = 0b00000;
8700 let Inst{12} = idx{2};
8701 let Inst{11-10} = idx{1-0};
8703 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8705 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8706 "$Rn = $wback", oops, iops, []> {
8707 // idx encoded in Q:S:size fields.
8710 let Inst{30} = idx{3};
8712 let Inst{20-16} = Xm;
8713 let Inst{12} = idx{2};
8714 let Inst{11-10} = idx{1-0};
8716 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8718 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8719 "$Rn = $wback", oops, iops, []> {
8720 // idx encoded in Q:S:size fields.
8723 let Inst{30} = idx{3};
8725 let Inst{20-16} = Xm;
8726 let Inst{12} = idx{2};
8727 let Inst{11-10} = idx{1-0};
8730 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8731 dag oops, dag iops, list<dag> pattern>
8732 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8734 // idx encoded in Q:S:size<1> fields.
8736 let Inst{30} = idx{2};
8738 let Inst{20-16} = 0b00000;
8739 let Inst{12} = idx{1};
8740 let Inst{11} = idx{0};
8741 let Inst{10} = size;
8743 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8744 dag oops, dag iops, list<dag> pattern>
8745 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8746 oops, iops, pattern> {
8747 // idx encoded in Q:S:size<1> fields.
8749 let Inst{30} = idx{2};
8751 let Inst{20-16} = 0b00000;
8752 let Inst{12} = idx{1};
8753 let Inst{11} = idx{0};
8754 let Inst{10} = size;
8757 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8759 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8760 "$Rn = $wback", oops, iops, []> {
8761 // idx encoded in Q:S:size<1> fields.
8764 let Inst{30} = idx{2};
8766 let Inst{20-16} = Xm;
8767 let Inst{12} = idx{1};
8768 let Inst{11} = idx{0};
8769 let Inst{10} = size;
8771 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8773 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8774 "$Rn = $wback", oops, iops, []> {
8775 // idx encoded in Q:S:size<1> fields.
8778 let Inst{30} = idx{2};
8780 let Inst{20-16} = Xm;
8781 let Inst{12} = idx{1};
8782 let Inst{11} = idx{0};
8783 let Inst{10} = size;
8785 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8786 dag oops, dag iops, list<dag> pattern>
8787 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8789 // idx encoded in Q:S fields.
8791 let Inst{30} = idx{1};
8793 let Inst{20-16} = 0b00000;
8794 let Inst{12} = idx{0};
8795 let Inst{11-10} = size;
8797 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8798 dag oops, dag iops, list<dag> pattern>
8799 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8800 oops, iops, pattern> {
8801 // idx encoded in Q:S fields.
8803 let Inst{30} = idx{1};
8805 let Inst{20-16} = 0b00000;
8806 let Inst{12} = idx{0};
8807 let Inst{11-10} = size;
8809 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8810 string asm, dag oops, dag iops>
8811 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8812 "$Rn = $wback", oops, iops, []> {
8813 // idx encoded in Q:S fields.
8816 let Inst{30} = idx{1};
8818 let Inst{20-16} = Xm;
8819 let Inst{12} = idx{0};
8820 let Inst{11-10} = size;
8822 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8823 string asm, dag oops, dag iops>
8824 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8825 "$Rn = $wback", oops, iops, []> {
8826 // idx encoded in Q:S fields.
8829 let Inst{30} = idx{1};
8831 let Inst{20-16} = Xm;
8832 let Inst{12} = idx{0};
8833 let Inst{11-10} = size;
8835 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8836 dag oops, dag iops, list<dag> pattern>
8837 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8839 // idx encoded in Q field.
8843 let Inst{20-16} = 0b00000;
8845 let Inst{11-10} = size;
8847 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8848 dag oops, dag iops, list<dag> pattern>
8849 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8850 oops, iops, pattern> {
8851 // idx encoded in Q field.
8855 let Inst{20-16} = 0b00000;
8857 let Inst{11-10} = size;
8859 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8860 string asm, dag oops, dag iops>
8861 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8862 "$Rn = $wback", oops, iops, []> {
8863 // idx encoded in Q field.
8868 let Inst{20-16} = Xm;
8870 let Inst{11-10} = size;
8872 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8873 string asm, dag oops, dag iops>
8874 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8875 "$Rn = $wback", oops, iops, []> {
8876 // idx encoded in Q field.
8881 let Inst{20-16} = Xm;
8883 let Inst{11-10} = size;
8886 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8887 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8888 RegisterOperand listtype,
8889 RegisterOperand GPR64pi> {
8890 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8891 (outs listtype:$dst),
8892 (ins listtype:$Vt, VectorIndexB:$idx,
8895 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8896 (outs GPR64sp:$wback, listtype:$dst),
8897 (ins listtype:$Vt, VectorIndexB:$idx,
8898 GPR64sp:$Rn, GPR64pi:$Xm)>;
8900 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8901 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8902 RegisterOperand listtype,
8903 RegisterOperand GPR64pi> {
8904 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8905 (outs listtype:$dst),
8906 (ins listtype:$Vt, VectorIndexH:$idx,
8909 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8910 (outs GPR64sp:$wback, listtype:$dst),
8911 (ins listtype:$Vt, VectorIndexH:$idx,
8912 GPR64sp:$Rn, GPR64pi:$Xm)>;
8914 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8915 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8916 RegisterOperand listtype,
8917 RegisterOperand GPR64pi> {
8918 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8919 (outs listtype:$dst),
8920 (ins listtype:$Vt, VectorIndexS:$idx,
8923 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8924 (outs GPR64sp:$wback, listtype:$dst),
8925 (ins listtype:$Vt, VectorIndexS:$idx,
8926 GPR64sp:$Rn, GPR64pi:$Xm)>;
8928 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8929 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8930 RegisterOperand listtype, RegisterOperand GPR64pi> {
8931 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8932 (outs listtype:$dst),
8933 (ins listtype:$Vt, VectorIndexD:$idx,
8936 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8937 (outs GPR64sp:$wback, listtype:$dst),
8938 (ins listtype:$Vt, VectorIndexD:$idx,
8939 GPR64sp:$Rn, GPR64pi:$Xm)>;
8941 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8942 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8943 RegisterOperand listtype, RegisterOperand GPR64pi> {
8944 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8945 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8948 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8949 (outs GPR64sp:$wback),
8950 (ins listtype:$Vt, VectorIndexB:$idx,
8951 GPR64sp:$Rn, GPR64pi:$Xm)>;
8953 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8954 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8955 RegisterOperand listtype, RegisterOperand GPR64pi> {
8956 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8957 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8960 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8961 (outs GPR64sp:$wback),
8962 (ins listtype:$Vt, VectorIndexH:$idx,
8963 GPR64sp:$Rn, GPR64pi:$Xm)>;
8965 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8966 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8967 RegisterOperand listtype, RegisterOperand GPR64pi> {
8968 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8969 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8972 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8973 (outs GPR64sp:$wback),
8974 (ins listtype:$Vt, VectorIndexS:$idx,
8975 GPR64sp:$Rn, GPR64pi:$Xm)>;
8977 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8978 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8979 RegisterOperand listtype, RegisterOperand GPR64pi> {
8980 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8981 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8984 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8985 (outs GPR64sp:$wback),
8986 (ins listtype:$Vt, VectorIndexD:$idx,
8987 GPR64sp:$Rn, GPR64pi:$Xm)>;
8990 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8991 string Count, int Offset, Operand idxtype> {
8992 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8993 // "ld1\t$Vt, [$Rn], #1"
8994 // may get mapped to
8995 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8996 def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8997 (!cast<Instruction>(NAME # Type # "_POST")
8999 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9000 idxtype:$idx, XZR), 1>;
9002 // E.g. "ld1.8b { v0 }[0], [x1], #1"
9003 // "ld1.8b\t$Vt, [$Rn], #1"
9004 // may get mapped to
9005 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9006 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9007 (!cast<Instruction>(NAME # Type # "_POST")
9009 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9010 idxtype:$idx, XZR), 0>;
9012 // E.g. "ld1.8b { v0 }[0], [x1]"
9013 // "ld1.8b\t$Vt, [$Rn]"
9014 // may get mapped to
9015 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9016 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9017 (!cast<Instruction>(NAME # Type)
9018 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9019 idxtype:$idx, GPR64sp:$Rn), 0>;
9021 // E.g. "ld1.8b { v0 }[0], [x1], x2"
9022 // "ld1.8b\t$Vt, [$Rn], $Xm"
9023 // may get mapped to
9024 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9025 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9026 (!cast<Instruction>(NAME # Type # "_POST")
9028 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9030 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9033 multiclass SIMDLdSt1SingleAliases<string asm> {
9034 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
9035 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9036 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9037 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9040 multiclass SIMDLdSt2SingleAliases<string asm> {
9041 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
9042 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
9043 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
9044 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9047 multiclass SIMDLdSt3SingleAliases<string asm> {
9048 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
9049 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
9050 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9051 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9054 multiclass SIMDLdSt4SingleAliases<string asm> {
9055 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
9056 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
9057 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9058 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9060 } // end of 'let Predicates = [HasNEON]'
9062 //----------------------------------------------------------------------------
9063 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9064 //----------------------------------------------------------------------------
9066 let Predicates = [HasNEON, HasV8_1a] in {
9068 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9069 RegisterOperand regtype, string asm,
9070 string kind, list<dag> pattern>
9071 : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9074 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9075 SDPatternOperator Accum> {
9076 def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9077 [(set (v4i16 V64:$dst),
9078 (Accum (v4i16 V64:$Rd),
9079 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9080 (v4i16 V64:$Rm)))))]>;
9081 def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9082 [(set (v8i16 V128:$dst),
9083 (Accum (v8i16 V128:$Rd),
9084 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9085 (v8i16 V128:$Rm)))))]>;
9086 def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9087 [(set (v2i32 V64:$dst),
9088 (Accum (v2i32 V64:$Rd),
9089 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9090 (v2i32 V64:$Rm)))))]>;
9091 def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9092 [(set (v4i32 V128:$dst),
9093 (Accum (v4i32 V128:$Rd),
9094 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9095 (v4i32 V128:$Rm)))))]>;
9098 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9099 SDPatternOperator Accum> {
9100 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9101 V64, V64, V128_lo, VectorIndexH,
9102 asm, ".4h", ".4h", ".4h", ".h",
9103 [(set (v4i16 V64:$dst),
9104 (Accum (v4i16 V64:$Rd),
9105 (v4i16 (int_aarch64_neon_sqrdmulh
9107 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9108 VectorIndexH:$idx))))))]> {
9110 let Inst{11} = idx{2};
9111 let Inst{21} = idx{1};
9112 let Inst{20} = idx{0};
9115 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9116 V128, V128, V128_lo, VectorIndexH,
9117 asm, ".8h", ".8h", ".8h", ".h",
9118 [(set (v8i16 V128:$dst),
9119 (Accum (v8i16 V128:$Rd),
9120 (v8i16 (int_aarch64_neon_sqrdmulh
9122 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9123 VectorIndexH:$idx))))))]> {
9125 let Inst{11} = idx{2};
9126 let Inst{21} = idx{1};
9127 let Inst{20} = idx{0};
9130 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9131 V64, V64, V128, VectorIndexS,
9132 asm, ".2s", ".2s", ".2s", ".s",
9133 [(set (v2i32 V64:$dst),
9134 (Accum (v2i32 V64:$Rd),
9135 (v2i32 (int_aarch64_neon_sqrdmulh
9137 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9138 VectorIndexS:$idx))))))]> {
9140 let Inst{11} = idx{1};
9141 let Inst{21} = idx{0};
9144 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9145 // an intermediate EXTRACT_SUBREG would be untyped.
9146 // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9147 // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9148 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9149 (i32 (vector_extract
9150 (v4i32 (insert_subvector
9152 (v2i32 (int_aarch64_neon_sqrdmulh
9154 (v2i32 (AArch64duplane32
9156 VectorIndexS:$idx)))),
9160 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9161 (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9166 VectorIndexS:$idx)),
9169 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9170 V128, V128, V128, VectorIndexS,
9171 asm, ".4s", ".4s", ".4s", ".s",
9172 [(set (v4i32 V128:$dst),
9173 (Accum (v4i32 V128:$Rd),
9174 (v4i32 (int_aarch64_neon_sqrdmulh
9176 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9177 VectorIndexS:$idx))))))]> {
9179 let Inst{11} = idx{1};
9180 let Inst{21} = idx{0};
9183 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9184 // an intermediate EXTRACT_SUBREG would be untyped.
9185 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9186 (i32 (vector_extract
9187 (v4i32 (int_aarch64_neon_sqrdmulh
9189 (v4i32 (AArch64duplane32
9191 VectorIndexS:$idx)))),
9194 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9195 (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9200 VectorIndexS:$idx)),
9203 def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9204 FPR16Op, FPR16Op, V128_lo,
9205 VectorIndexH, asm, ".h", "", "", ".h",
9208 let Inst{11} = idx{2};
9209 let Inst{21} = idx{1};
9210 let Inst{20} = idx{0};
9213 def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9214 FPR32Op, FPR32Op, V128, VectorIndexS,
9215 asm, ".s", "", "", ".s",
9216 [(set (i32 FPR32Op:$dst),
9217 (Accum (i32 FPR32Op:$Rd),
9218 (i32 (int_aarch64_neon_sqrdmulh
9220 (i32 (vector_extract (v4i32 V128:$Rm),
9221 VectorIndexS:$idx))))))]> {
9223 let Inst{11} = idx{1};
9224 let Inst{21} = idx{0};
9227 } // let Predicates = [HasNeon, HasV8_1a]
9229 //----------------------------------------------------------------------------
9230 // Crypto extensions
9231 //----------------------------------------------------------------------------
9233 let Predicates = [HasCrypto] in {
9234 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9235 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
9237 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
9241 let Inst{31-16} = 0b0100111000101000;
9242 let Inst{15-12} = opc;
9243 let Inst{11-10} = 0b10;
9248 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9249 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9250 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9252 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9253 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9255 [(set (v16i8 V128:$dst),
9256 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9258 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9259 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9260 dag oops, dag iops, list<dag> pat>
9261 : I<oops, iops, asm,
9262 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9263 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9268 let Inst{31-21} = 0b01011110000;
9269 let Inst{20-16} = Rm;
9271 let Inst{14-12} = opc;
9272 let Inst{11-10} = 0b00;
9277 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9278 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9279 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9280 [(set (v4i32 FPR128:$dst),
9281 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9282 (v4i32 V128:$Rm)))]>;
9284 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9285 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9286 (ins V128:$Rd, V128:$Rn, V128:$Rm),
9287 [(set (v4i32 V128:$dst),
9288 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9289 (v4i32 V128:$Rm)))]>;
9291 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9292 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9293 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9294 [(set (v4i32 FPR128:$dst),
9295 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
9296 (v4i32 V128:$Rm)))]>;
9298 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9299 class SHA2OpInst<bits<4> opc, string asm, string kind,
9300 string cstr, dag oops, dag iops,
9302 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
9303 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
9307 let Inst{31-16} = 0b0101111000101000;
9308 let Inst{15-12} = opc;
9309 let Inst{11-10} = 0b10;
9314 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
9315 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
9316 (ins V128:$Rd, V128:$Rn),
9317 [(set (v4i32 V128:$dst),
9318 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
9320 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
9321 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
9322 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
9323 } // end of 'let Predicates = [HasCrypto]'
9325 //----------------------------------------------------------------------------
9326 // v8.1 atomic instructions extension:
9330 // * LDOPregister<OP>, and aliases STOPregister<OP>
9332 // Instruction encodings:
9334 // 31 30|29 24|23|22|21|20 16|15|14 10|9 5|4 0
9335 // CAS SZ |001000|1 |A |1 |Rs |R |11111 |Rn |Rt
9336 // CASP 0|SZ|001000|0 |A |1 |Rs |R |11111 |Rn |Rt
9337 // SWP SZ |111000|A |R |1 |Rs |1 |OPC|00|Rn |Rt
9338 // LD SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |Rt
9339 // ST SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |11111
9341 // Instruction syntax:
9343 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9344 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
9345 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
9346 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
9347 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9348 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
9349 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9350 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
9351 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
9352 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
9354 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9355 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
9356 string cstr, list<dag> pattern>
9357 : I<oops, iops, asm, operands, cstr, pattern> {
9365 let Inst{31-30} = Sz;
9366 let Inst{29-24} = 0b001000;
9370 let Inst{20-16} = Rs;
9372 let Inst{14-10} = 0b11111;
9377 class BaseCAS<string order, string size, RegisterClass RC>
9378 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9379 "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
9384 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
9385 let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
9386 let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
9387 let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
9388 let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
9391 class BaseCASP<string order, string size, RegisterOperand RC>
9392 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9393 "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
9398 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
9399 let Sz = 0b00, Acq = Acq, Rel = Rel in
9400 def s : BaseCASP<order, "", WSeqPairClassOperand>;
9401 let Sz = 0b01, Acq = Acq, Rel = Rel in
9402 def d : BaseCASP<order, "", XSeqPairClassOperand>;
9405 let Predicates = [HasV8_1a] in
9406 class BaseSWP<string order, string size, RegisterClass RC>
9407 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
9408 "\t$Rs, $Rt, [$Rn]","",[]> {
9413 bits<3> opc = 0b000;
9416 let Inst{31-30} = Sz;
9417 let Inst{29-24} = 0b111000;
9421 let Inst{20-16} = Rs;
9423 let Inst{14-12} = opc;
9424 let Inst{11-10} = 0b00;
9429 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
9430 let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
9431 let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
9432 let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
9433 let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
9436 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9437 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
9438 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
9439 "\t$Rs, $Rt, [$Rn]","",[]> {
9447 let Inst{31-30} = Sz;
9448 let Inst{29-24} = 0b111000;
9452 let Inst{20-16} = Rs;
9454 let Inst{14-12} = opc;
9455 let Inst{11-10} = 0b00;
9460 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
9462 let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
9463 def b : BaseLDOPregister<op, order, "b", GPR32>;
9464 let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
9465 def h : BaseLDOPregister<op, order, "h", GPR32>;
9466 let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
9467 def s : BaseLDOPregister<op, order, "", GPR32>;
9468 let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
9469 def d : BaseLDOPregister<op, order, "", GPR64>;
9472 let Predicates = [HasV8_1a] in
9473 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9475 InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9477 multiclass STOPregister<string asm, string instr> {
9478 def : BaseSTOPregister<asm # "lb", GPR32, WZR,
9479 !cast<Instruction>(instr # "Lb")>;
9480 def : BaseSTOPregister<asm # "lh", GPR32, WZR,
9481 !cast<Instruction>(instr # "Lh")>;
9482 def : BaseSTOPregister<asm # "l", GPR32, WZR,
9483 !cast<Instruction>(instr # "Ls")>;
9484 def : BaseSTOPregister<asm # "l", GPR64, XZR,
9485 !cast<Instruction>(instr # "Ld")>;
9486 def : BaseSTOPregister<asm # "b", GPR32, WZR,
9487 !cast<Instruction>(instr # "b")>;
9488 def : BaseSTOPregister<asm # "h", GPR32, WZR,
9489 !cast<Instruction>(instr # "h")>;
9490 def : BaseSTOPregister<asm, GPR32, WZR,
9491 !cast<Instruction>(instr # "s")>;
9492 def : BaseSTOPregister<asm, GPR64, XZR,
9493 !cast<Instruction>(instr # "d")>;
9496 //----------------------------------------------------------------------------
9497 // Allow the size specifier tokens to be upper case, not just lower.
9498 def : TokenAlias<".8B", ".8b">;
9499 def : TokenAlias<".4H", ".4h">;
9500 def : TokenAlias<".2S", ".2s">;
9501 def : TokenAlias<".1D", ".1d">;
9502 def : TokenAlias<".16B", ".16b">;
9503 def : TokenAlias<".8H", ".8h">;
9504 def : TokenAlias<".4S", ".4s">;
9505 def : TokenAlias<".2D", ".2d">;
9506 def : TokenAlias<".1Q", ".1q">;
9507 def : TokenAlias<".2H", ".2h">;
9508 def : TokenAlias<".B", ".b">;
9509 def : TokenAlias<".H", ".h">;
9510 def : TokenAlias<".S", ".s">;
9511 def : TokenAlias<".D", ".d">;
9512 def : TokenAlias<".Q", ".q">;