[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / AArch64 / AArch64InstrFormats.td
blob9bc2539e95f086dfffb771eaff94549242841f29
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
10 //  Describe AArch64 instructions format here
13 // Format specifies the encoding used by the instruction.  This is part of the
14 // ad-hoc solution used to emit machine instruction encodings by our machine
15 // code emitter.
16 class Format<bits<2> val> {
17   bits<2> Value = val;
20 def PseudoFrm   : Format<0>;
21 def NormalFrm   : Format<1>; // Do we need any others?
23 // Enum describing whether an instruction is
24 // destructive in its first source operand.
25 class DestructiveInstTypeEnum<bits<4> val> {
26   bits<4> Value = val;
28 def NotDestructive                : DestructiveInstTypeEnum<0>;
29 // Destructive in its first operand and can be MOVPRFX'd, but has no other
30 // special properties.
31 def DestructiveOther              : DestructiveInstTypeEnum<1>;
32 def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33 def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34 def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35 def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36 def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37 def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38 def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39 def DestructiveUnaryPassthru      : DestructiveInstTypeEnum<9>;
41 class FalseLanesEnum<bits<2> val> {
42   bits<2> Value = val;
44 def FalseLanesNone  : FalseLanesEnum<0>;
45 def FalseLanesZero  : FalseLanesEnum<1>;
46 def FalseLanesUndef : FalseLanesEnum<2>;
48 // AArch64 Instruction Format
49 class AArch64Inst<Format f, string cstr> : Instruction {
50   field bits<32> Inst; // Instruction encoding.
51   // Mask of bits that cause an encoding to be UNPREDICTABLE.
52   // If a bit is set, then if the corresponding bit in the
53   // target encoding differs from its value in the "Inst" field,
54   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
55   field bits<32> Unpredictable = 0;
56   // SoftFail is the generic name for this field, but we alias it so
57   // as to make it more obvious what it means in ARM-land.
58   field bits<32> SoftFail = Unpredictable;
59   let Namespace   = "AArch64";
60   Format F        = f;
61   bits<2> Form    = F.Value;
63   // Defaults
64   bit isWhile = 0;
65   bit isPTestLike = 0;
66   FalseLanesEnum FalseLanes = FalseLanesNone;
67   DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
68   ElementSizeEnum ElementSize = ElementSizeNone;
70   let TSFlags{10}  = isPTestLike;
71   let TSFlags{9}   = isWhile;
72   let TSFlags{8-7} = FalseLanes.Value;
73   let TSFlags{6-3} = DestructiveInstType.Value;
74   let TSFlags{2-0} = ElementSize.Value;
76   let Pattern     = [];
77   let Constraints = cstr;
80 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
81   : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
83 // Pseudo instructions (don't have encoding information)
84 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
85     : AArch64Inst<PseudoFrm, cstr> {
86   dag OutOperandList = oops;
87   dag InOperandList  = iops;
88   let Pattern        = pattern;
89   let isCodeGenOnly  = 1;
90   let isPseudo       = 1;
93 // Real instructions (have encoding information)
94 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
95   let Pattern = pattern;
96   let Size = 4;
99 // Normal instructions
100 class I<dag oops, dag iops, string asm, string operands, string cstr,
101         list<dag> pattern>
102     : EncodedI<cstr, pattern> {
103   dag OutOperandList = oops;
104   dag InOperandList  = iops;
105   let AsmString      = !strconcat(asm, operands);
108 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
109 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
110 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
112 // Helper fragment for an extract of the high portion of a 128-bit vector.
113 def extract_high_v16i8 :
114    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
115 def extract_high_v8i16 :
116    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
117 def extract_high_v4i32 :
118    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
119 def extract_high_v2i64 :
120    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
122 //===----------------------------------------------------------------------===//
123 // Asm Operand Classes.
126 // Shifter operand for arithmetic shifted encodings.
127 def ShifterOperand : AsmOperandClass {
128   let Name = "Shifter";
131 // Shifter operand for mov immediate encodings.
132 def MovImm32ShifterOperand : AsmOperandClass {
133   let SuperClasses = [ShifterOperand];
134   let Name = "MovImm32Shifter";
135   let RenderMethod = "addShifterOperands";
136   let DiagnosticType = "InvalidMovImm32Shift";
138 def MovImm64ShifterOperand : AsmOperandClass {
139   let SuperClasses = [ShifterOperand];
140   let Name = "MovImm64Shifter";
141   let RenderMethod = "addShifterOperands";
142   let DiagnosticType = "InvalidMovImm64Shift";
145 // Shifter operand for arithmetic register shifted encodings.
146 class ArithmeticShifterOperand<int width> : AsmOperandClass {
147   let SuperClasses = [ShifterOperand];
148   let Name = "ArithmeticShifter" # width;
149   let PredicateMethod = "isArithmeticShifter<" # width # ">";
150   let RenderMethod = "addShifterOperands";
151   let DiagnosticType = "AddSubRegShift" # width;
154 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
155 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
157 // Shifter operand for logical register shifted encodings.
158 class LogicalShifterOperand<int width> : AsmOperandClass {
159   let SuperClasses = [ShifterOperand];
160   let Name = "LogicalShifter" # width;
161   let PredicateMethod = "isLogicalShifter<" # width # ">";
162   let RenderMethod = "addShifterOperands";
163   let DiagnosticType = "AddSubRegShift" # width;
166 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
167 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
169 // Shifter operand for logical vector 128/64-bit shifted encodings.
170 def LogicalVecShifterOperand : AsmOperandClass {
171   let SuperClasses = [ShifterOperand];
172   let Name = "LogicalVecShifter";
173   let RenderMethod = "addShifterOperands";
175 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
176   let SuperClasses = [LogicalVecShifterOperand];
177   let Name = "LogicalVecHalfWordShifter";
178   let RenderMethod = "addShifterOperands";
181 // The "MSL" shifter on the vector MOVI instruction.
182 def MoveVecShifterOperand : AsmOperandClass {
183   let SuperClasses = [ShifterOperand];
184   let Name = "MoveVecShifter";
185   let RenderMethod = "addShifterOperands";
188 // Extend operand for arithmetic encodings.
189 def ExtendOperand : AsmOperandClass {
190   let Name = "Extend";
191   let DiagnosticType = "AddSubRegExtendLarge";
193 def ExtendOperand64 : AsmOperandClass {
194   let SuperClasses = [ExtendOperand];
195   let Name = "Extend64";
196   let DiagnosticType = "AddSubRegExtendSmall";
198 // 'extend' that's a lsl of a 64-bit register.
199 def ExtendOperandLSL64 : AsmOperandClass {
200   let SuperClasses = [ExtendOperand];
201   let Name = "ExtendLSL64";
202   let RenderMethod = "addExtend64Operands";
203   let DiagnosticType = "AddSubRegExtendLarge";
206 // 8-bit floating-point immediate encodings.
207 def FPImmOperand : AsmOperandClass {
208   let Name = "FPImm";
209   let ParserMethod = "tryParseFPImm<true>";
210   let DiagnosticType = "InvalidFPImm";
213 def CondCode : AsmOperandClass {
214   let Name = "CondCode";
215   let DiagnosticType = "InvalidCondCode";
218 // A 32-bit register pasrsed as 64-bit
219 def GPR32as64Operand : AsmOperandClass {
220   let Name = "GPR32as64";
221   let ParserMethod =
222       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
224 def GPR32as64 : RegisterOperand<GPR32> {
225   let ParserMatchClass = GPR32as64Operand;
228 // A 64-bit register pasrsed as 32-bit
229 def GPR64as32Operand : AsmOperandClass {
230   let Name = "GPR64as32";
231   let ParserMethod =
232       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
234 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
235   let ParserMatchClass = GPR64as32Operand;
238 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
239 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
240 // are encoded as the eight bit value 'abcdefgh'.
241 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
243 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
244   let Name = "UImm" # Width # "s" # Scale;
245   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
246   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
247   let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
250 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
251   let Name = "SImm" # Width # "s" # Scale;
252   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
253   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
254   let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
257 //===----------------------------------------------------------------------===//
258 // Operand Definitions.
261 // ADR[P] instruction labels.
262 def AdrpOperand : AsmOperandClass {
263   let Name = "AdrpLabel";
264   let ParserMethod = "tryParseAdrpLabel";
265   let DiagnosticType = "InvalidLabel";
267 def adrplabel : Operand<i64> {
268   let EncoderMethod = "getAdrLabelOpValue";
269   let PrintMethod = "printAdrpLabel";
270   let ParserMatchClass = AdrpOperand;
271   let OperandType = "OPERAND_PCREL";
274 def AdrOperand : AsmOperandClass {
275   let Name = "AdrLabel";
276   let ParserMethod = "tryParseAdrLabel";
277   let DiagnosticType = "InvalidLabel";
279 def adrlabel : Operand<i64> {
280   let EncoderMethod = "getAdrLabelOpValue";
281   let ParserMatchClass = AdrOperand;
284 class SImmOperand<int width> : AsmOperandClass {
285   let Name = "SImm" # width;
286   let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
287   let RenderMethod = "addImmOperands";
288   let PredicateMethod = "isSImm<" # width # ">";
292 class AsmImmRange<int Low, int High> : AsmOperandClass {
293   let Name = "Imm" # Low # "_" # High;
294   let DiagnosticType = "InvalidImm" # Low # "_" # High;
295   let RenderMethod = "addImmOperands";
296   let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
299 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
300 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
301 def simm10Scaled : Operand<i64> {
302   let ParserMatchClass = SImm10s8Operand;
303   let DecoderMethod = "DecodeSImm<10>";
304   let PrintMethod = "printImmScale<8>";
307 def simm9s16 : Operand<i64> {
308   let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
309   let DecoderMethod = "DecodeSImm<9>";
310   let PrintMethod = "printImmScale<16>";
313 // uimm6 predicate - True if the immediate is in the range [0, 63].
314 def UImm6Operand : AsmOperandClass {
315   let Name = "UImm6";
316   let DiagnosticType = "InvalidImm0_63";
319 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
320   let ParserMatchClass = UImm6Operand;
323 def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
324   let ParserMatchClass = AsmImmRange<0, 65535>;
327 def SImm9Operand : SImmOperand<9>;
328 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
329   let ParserMatchClass = SImm9Operand;
330   let DecoderMethod = "DecodeSImm<9>";
333 def SImm8Operand : SImmOperand<8>;
334 def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
335   let ParserMatchClass = SImm8Operand;
336   let DecoderMethod = "DecodeSImm<8>";
339 def SImm6Operand : SImmOperand<6>;
340 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
341   let ParserMatchClass = SImm6Operand;
342   let DecoderMethod = "DecodeSImm<6>";
345 def SImm5Operand : SImmOperand<5>;
346 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
347   let ParserMatchClass = SImm5Operand;
348   let DecoderMethod = "DecodeSImm<5>";
351 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
352   let ParserMatchClass = SImm5Operand;
353   let DecoderMethod = "DecodeSImm<5>";
356 def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
357   let ParserMatchClass = SImm5Operand;
358   let DecoderMethod = "DecodeSImm<5>";
359   let PrintMethod = "printSImm<8>";
362 def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
363   let ParserMatchClass = SImm5Operand;
364   let DecoderMethod = "DecodeSImm<5>";
365   let PrintMethod = "printSImm<16>";
368 // simm7sN predicate - True if the immediate is a multiple of N in the range
369 // [-64 * N, 63 * N].
371 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
372 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
373 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
375 def simm7s4 : Operand<i32> {
376   let ParserMatchClass = SImm7s4Operand;
377   let PrintMethod = "printImmScale<4>";
380 def simm7s8 : Operand<i32> {
381   let ParserMatchClass = SImm7s8Operand;
382   let PrintMethod = "printImmScale<8>";
385 def simm7s16 : Operand<i32> {
386   let ParserMatchClass = SImm7s16Operand;
387   let PrintMethod = "printImmScale<16>";
390 def am_sve_fi : ComplexPattern<i64, 2, "SelectAddrModeFrameIndexSVE", []>;
392 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
393 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
394 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
395 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
396 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
398 def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
399 def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
401 def UImmS1XForm : SDNodeXForm<imm, [{
402   return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
403 }]>;
404 def UImmS2XForm : SDNodeXForm<imm, [{
405   return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
406 }]>;
407 def UImmS4XForm : SDNodeXForm<imm, [{
408   return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
409 }]>;
410 def UImmS8XForm : SDNodeXForm<imm, [{
411   return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
412 }]>;
414 // uimm5sN predicate - True if the immediate is a multiple of N in the range
415 // [0 * N, 32 * N].
416 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
417 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
418 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
420 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
421                 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
422                 UImmS2XForm> {
423   let ParserMatchClass = UImm5s2Operand;
424   let PrintMethod = "printImmScale<2>";
426 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
427                 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
428                 UImmS4XForm> {
429   let ParserMatchClass = UImm5s4Operand;
430   let PrintMethod = "printImmScale<4>";
432 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
433                 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
434                 UImmS8XForm> {
435   let ParserMatchClass = UImm5s8Operand;
436   let PrintMethod = "printImmScale<8>";
439 // tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
440 // instead of ImmLeaf (Constant)
441 def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
442                 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
443                 UImmS2XForm> {
444   let ParserMatchClass = UImm5s2Operand;
445   let PrintMethod = "printImmScale<2>";
447 def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
448                 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
449                 UImmS4XForm> {
450   let ParserMatchClass = UImm5s4Operand;
451   let PrintMethod = "printImmScale<4>";
453 def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
454                 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
455                 UImmS8XForm> {
456   let ParserMatchClass = UImm5s8Operand;
457   let PrintMethod = "printImmScale<8>";
460 // uimm6sN predicate - True if the immediate is a multiple of N in the range
461 // [0 * N, 64 * N].
462 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
463 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
464 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
465 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
466 def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
468 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
469   let ParserMatchClass = UImm6s1Operand;
471 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
472 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
473   let PrintMethod = "printImmScale<2>";
474   let ParserMatchClass = UImm6s2Operand;
476 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
477 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
478   let PrintMethod = "printImmScale<4>";
479   let ParserMatchClass = UImm6s4Operand;
481 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
482 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
483   let PrintMethod = "printImmScale<8>";
484   let ParserMatchClass = UImm6s8Operand;
486 def uimm6s16 : Operand<i64>, ImmLeaf<i64,
487 [{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
488   let PrintMethod = "printImmScale<16>";
489   let ParserMatchClass = UImm6s16Operand;
492 def SImmS2XForm : SDNodeXForm<imm, [{
493   return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
494 }]>;
495 def SImmS3XForm : SDNodeXForm<imm, [{
496   return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
497 }]>;
498 def SImmS4XForm : SDNodeXForm<imm, [{
499   return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
500 }]>;
501 def SImmS16XForm : SDNodeXForm<imm, [{
502   return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
503 }]>;
504 def SImmS32XForm : SDNodeXForm<imm, [{
505   return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
506 }]>;
508 // simm6sN predicate - True if the immediate is a multiple of N in the range
509 // [-32 * N, 31 * N].
510 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
511 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
512   let ParserMatchClass = SImm6s1Operand;
513   let DecoderMethod = "DecodeSImm<6>";
516 // simm4sN predicate - True if the immediate is a multiple of N in the range
517 // [ -8* N, 7 * N].
518 def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
519 def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
520 def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
521 def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
522 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
523 def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
525 def simm4s1 : Operand<i64>, ImmLeaf<i64,
526 [{ return Imm >=-8  && Imm <= 7; }]> {
527   let ParserMatchClass = SImm4s1Operand;
528   let DecoderMethod = "DecodeSImm<4>";
531 def simm4s2 : Operand<i64>, ImmLeaf<i64,
532 [{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
533   let PrintMethod = "printImmScale<2>";
534   let ParserMatchClass = SImm4s2Operand;
535   let DecoderMethod = "DecodeSImm<4>";
538 def simm4s3 : Operand<i64>, ImmLeaf<i64,
539 [{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
540   let PrintMethod = "printImmScale<3>";
541   let ParserMatchClass = SImm4s3Operand;
542   let DecoderMethod = "DecodeSImm<4>";
545 def simm4s4 : Operand<i64>, ImmLeaf<i64,
546 [{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
547   let PrintMethod = "printImmScale<4>";
548   let ParserMatchClass = SImm4s4Operand;
549   let DecoderMethod = "DecodeSImm<4>";
551 def simm4s16 : Operand<i64>, ImmLeaf<i64,
552 [{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
553   let PrintMethod = "printImmScale<16>";
554   let ParserMatchClass = SImm4s16Operand;
555   let DecoderMethod = "DecodeSImm<4>";
557 def simm4s32 : Operand<i64>, ImmLeaf<i64,
558 [{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
559   let PrintMethod = "printImmScale<32>";
560   let ParserMatchClass = SImm4s32Operand;
561   let DecoderMethod = "DecodeSImm<4>";
564 def Imm1_8Operand : AsmImmRange<1, 8>;
565 def Imm1_16Operand : AsmImmRange<1, 16>;
566 def Imm1_32Operand : AsmImmRange<1, 32>;
567 def Imm1_64Operand : AsmImmRange<1, 64>;
569 class BranchTarget<int N> : AsmOperandClass {
570   let Name = "BranchTarget" # N;
571   let DiagnosticType = "InvalidLabel";
572   let PredicateMethod = "isBranchTarget<" # N # ">";
575 class PCRelLabel<int N> : BranchTarget<N> {
576   let Name = "PCRelLabel" # N;
579 def BranchTarget14Operand : BranchTarget<14>;
580 def BranchTarget26Operand : BranchTarget<26>;
581 def PCRelLabel19Operand   : PCRelLabel<19>;
583 def MovWSymbolG3AsmOperand : AsmOperandClass {
584   let Name = "MovWSymbolG3";
585   let RenderMethod = "addImmOperands";
588 def movw_symbol_g3 : Operand<i32> {
589   let ParserMatchClass = MovWSymbolG3AsmOperand;
592 def MovWSymbolG2AsmOperand : AsmOperandClass {
593   let Name = "MovWSymbolG2";
594   let RenderMethod = "addImmOperands";
597 def movw_symbol_g2 : Operand<i32> {
598   let ParserMatchClass = MovWSymbolG2AsmOperand;
601 def MovWSymbolG1AsmOperand : AsmOperandClass {
602   let Name = "MovWSymbolG1";
603   let RenderMethod = "addImmOperands";
606 def movw_symbol_g1 : Operand<i32> {
607   let ParserMatchClass = MovWSymbolG1AsmOperand;
610 def MovWSymbolG0AsmOperand : AsmOperandClass {
611   let Name = "MovWSymbolG0";
612   let RenderMethod = "addImmOperands";
615 def movw_symbol_g0 : Operand<i32> {
616   let ParserMatchClass = MovWSymbolG0AsmOperand;
619 class fixedpoint_i32<ValueType FloatVT>
620   : Operand<FloatVT>,
621     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
622   let EncoderMethod = "getFixedPointScaleOpValue";
623   let DecoderMethod = "DecodeFixedPointScaleImm32";
624   let ParserMatchClass = Imm1_32Operand;
627 class fixedpoint_i64<ValueType FloatVT>
628   : Operand<FloatVT>,
629     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
630   let EncoderMethod = "getFixedPointScaleOpValue";
631   let DecoderMethod = "DecodeFixedPointScaleImm64";
632   let ParserMatchClass = Imm1_64Operand;
635 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
636 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
637 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
639 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
640 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
641 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
643 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
644   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
645 }]> {
646   let EncoderMethod = "getVecShiftR8OpValue";
647   let DecoderMethod = "DecodeVecShiftR8Imm";
648   let ParserMatchClass = Imm1_8Operand;
650 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
651   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
652 }]> {
653   let EncoderMethod = "getVecShiftR16OpValue";
654   let DecoderMethod = "DecodeVecShiftR16Imm";
655   let ParserMatchClass = Imm1_16Operand;
657 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
658   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
659 }]> {
660   let EncoderMethod = "getVecShiftR16OpValue";
661   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
662   let ParserMatchClass = Imm1_8Operand;
664 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
665   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
666 }]> {
667   let EncoderMethod = "getVecShiftR32OpValue";
668   let DecoderMethod = "DecodeVecShiftR32Imm";
669   let ParserMatchClass = Imm1_32Operand;
671 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
672   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
673 }]> {
674   let EncoderMethod = "getVecShiftR32OpValue";
675   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
676   let ParserMatchClass = Imm1_16Operand;
678 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
679   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
680 }]> {
681   let EncoderMethod = "getVecShiftR64OpValue";
682   let DecoderMethod = "DecodeVecShiftR64Imm";
683   let ParserMatchClass = Imm1_64Operand;
685 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
686   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
687 }]> {
688   let EncoderMethod = "getVecShiftR64OpValue";
689   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
690   let ParserMatchClass = Imm1_32Operand;
693 // Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
694 // (ImmLeaf)
695 def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
696   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
697 }]> {
698   let EncoderMethod = "getVecShiftR8OpValue";
699   let DecoderMethod = "DecodeVecShiftR8Imm";
700   let ParserMatchClass = Imm1_8Operand;
702 def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
703   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
704 }]> {
705   let EncoderMethod = "getVecShiftR16OpValue";
706   let DecoderMethod = "DecodeVecShiftR16Imm";
707   let ParserMatchClass = Imm1_16Operand;
709 def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
710   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
711 }]> {
712   let EncoderMethod = "getVecShiftR32OpValue";
713   let DecoderMethod = "DecodeVecShiftR32Imm";
714   let ParserMatchClass = Imm1_32Operand;
716 def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
717   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
718 }]> {
719   let EncoderMethod = "getVecShiftR64OpValue";
720   let DecoderMethod = "DecodeVecShiftR64Imm";
721   let ParserMatchClass = Imm1_64Operand;
724 def Imm0_1Operand : AsmImmRange<0, 1>;
725 def Imm0_3Operand : AsmImmRange<0, 3>;
726 def Imm0_7Operand : AsmImmRange<0, 7>;
727 def Imm0_15Operand : AsmImmRange<0, 15>;
728 def Imm0_31Operand : AsmImmRange<0, 31>;
729 def Imm0_63Operand : AsmImmRange<0, 63>;
731 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
732   return (((uint32_t)Imm) < 8);
733 }]> {
734   let EncoderMethod = "getVecShiftL8OpValue";
735   let DecoderMethod = "DecodeVecShiftL8Imm";
736   let ParserMatchClass = Imm0_7Operand;
738 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
739   return (((uint32_t)Imm) < 16);
740 }]> {
741   let EncoderMethod = "getVecShiftL16OpValue";
742   let DecoderMethod = "DecodeVecShiftL16Imm";
743   let ParserMatchClass = Imm0_15Operand;
745 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
746   return (((uint32_t)Imm) < 32);
747 }]> {
748   let EncoderMethod = "getVecShiftL32OpValue";
749   let DecoderMethod = "DecodeVecShiftL32Imm";
750   let ParserMatchClass = Imm0_31Operand;
752 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
753   return (((uint32_t)Imm) < 64);
754 }]> {
755   let EncoderMethod = "getVecShiftL64OpValue";
756   let DecoderMethod = "DecodeVecShiftL64Imm";
757   let ParserMatchClass = Imm0_63Operand;
760 // Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
761 // (ImmLeaf)
762 def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
763   return (((uint32_t)Imm) < 8);
764 }]> {
765   let EncoderMethod = "getVecShiftL8OpValue";
766   let DecoderMethod = "DecodeVecShiftL8Imm";
767   let ParserMatchClass = Imm0_7Operand;
769 def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
770   return (((uint32_t)Imm) < 16);
771 }]> {
772   let EncoderMethod = "getVecShiftL16OpValue";
773   let DecoderMethod = "DecodeVecShiftL16Imm";
774   let ParserMatchClass = Imm0_15Operand;
776 def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
777   return (((uint32_t)Imm) < 32);
778 }]> {
779   let EncoderMethod = "getVecShiftL32OpValue";
780   let DecoderMethod = "DecodeVecShiftL32Imm";
781   let ParserMatchClass = Imm0_31Operand;
783 def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
784   return (((uint32_t)Imm) < 64);
785 }]> {
786   let EncoderMethod = "getVecShiftL64OpValue";
787   let DecoderMethod = "DecodeVecShiftL64Imm";
788   let ParserMatchClass = Imm0_63Operand;
791 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
792 // instructions for splatting repeating bit patterns across the immediate.
793 def logical_imm32_XFORM : SDNodeXForm<imm, [{
794   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
795   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
796 }]>;
797 def logical_imm64_XFORM : SDNodeXForm<imm, [{
798   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
799   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
800 }]>;
802 def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
803   GISDNodeXFormEquiv<logical_imm32_XFORM>;
804 def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
805   GISDNodeXFormEquiv<logical_imm64_XFORM>;
807 let DiagnosticType = "LogicalSecondSource" in {
808   def LogicalImm32Operand : AsmOperandClass {
809     let Name = "LogicalImm32";
810     let PredicateMethod = "isLogicalImm<int32_t>";
811     let RenderMethod = "addLogicalImmOperands<int32_t>";
812   }
813   def LogicalImm64Operand : AsmOperandClass {
814     let Name = "LogicalImm64";
815     let PredicateMethod = "isLogicalImm<int64_t>";
816     let RenderMethod = "addLogicalImmOperands<int64_t>";
817   }
818   def LogicalImm32NotOperand : AsmOperandClass {
819     let Name = "LogicalImm32Not";
820     let PredicateMethod = "isLogicalImm<int32_t>";
821     let RenderMethod = "addLogicalImmNotOperands<int32_t>";
822   }
823   def LogicalImm64NotOperand : AsmOperandClass {
824     let Name = "LogicalImm64Not";
825     let PredicateMethod = "isLogicalImm<int64_t>";
826     let RenderMethod = "addLogicalImmNotOperands<int64_t>";
827   }
829 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
830   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
831 }], logical_imm32_XFORM> {
832   let PrintMethod = "printLogicalImm<int32_t>";
833   let ParserMatchClass = LogicalImm32Operand;
835 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
836   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
837 }], logical_imm64_XFORM> {
838   let PrintMethod = "printLogicalImm<int64_t>";
839   let ParserMatchClass = LogicalImm64Operand;
841 def logical_imm32_not : Operand<i32> {
842   let ParserMatchClass = LogicalImm32NotOperand;
844 def logical_imm64_not : Operand<i64> {
845   let ParserMatchClass = LogicalImm64NotOperand;
848 // iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
849 let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
850 def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
851   return ((uint32_t)Imm) < 65536;
852 }]>;
854 def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
855   return ((uint64_t)Imm) < 65536;
856 }]>;
859 // imm0_255 predicate - True if the immediate is in the range [0,255].
860 def Imm0_255Operand : AsmImmRange<0,255>;
862 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
863   return ((uint32_t)Imm) < 256;
864 }]> {
865   let ParserMatchClass = Imm0_255Operand;
866   let PrintMethod = "printImm";
869 // imm0_127 predicate - True if the immediate is in the range [0,127]
870 def Imm0_127Operand : AsmImmRange<0, 127>;
871 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
872   return ((uint32_t)Imm) < 128;
873 }]> {
874   let ParserMatchClass = Imm0_127Operand;
875   let PrintMethod = "printImm";
878 def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
879   return ((uint64_t)Imm) < 128;
880 }]> {
881   let ParserMatchClass = Imm0_127Operand;
882   let PrintMethod = "printImm";
885 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
886 // for all shift-amounts.
888 // imm0_63 predicate - True if the immediate is in the range [0,63]
889 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
890   return ((uint64_t)Imm) < 64;
891 }]> {
892   let ParserMatchClass = Imm0_63Operand;
895 def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
896   return ((uint64_t)Imm) < 64;
897 }]> {
898   let ParserMatchClass = Imm0_63Operand;
901 // imm0_31 predicate - True if the immediate is in the range [0,31]
902 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
903   return ((uint64_t)Imm) < 32;
904 }]> {
905   let ParserMatchClass = Imm0_31Operand;
908 // timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
909 // instead of Constant (ImmLeaf)
910 def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
911   return ((uint64_t)Imm) < 32;
912 }]> {
913   let ParserMatchClass = Imm0_31Operand;
916 // True if the 32-bit immediate is in the range [0,31]
917 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
918   return ((uint64_t)Imm) < 32;
919 }]> {
920   let ParserMatchClass = Imm0_31Operand;
923 // imm0_1 predicate - True if the immediate is in the range [0,1]
924 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
925   return ((uint64_t)Imm) < 2;
926 }]> {
927   let ParserMatchClass = Imm0_1Operand;
930 // timm0_1 - as above, but use TargetConstant (TImmLeaf)
931 def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
932   return ((uint64_t)Imm) < 2;
933 }]> {
934   let ParserMatchClass = Imm0_1Operand;
937 // imm0_15 predicate - True if the immediate is in the range [0,15]
938 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
939   return ((uint64_t)Imm) < 16;
940 }]> {
941   let ParserMatchClass = Imm0_15Operand;
944 // imm0_7 predicate - True if the immediate is in the range [0,7]
945 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
946   return ((uint64_t)Imm) < 8;
947 }]> {
948   let ParserMatchClass = Imm0_7Operand;
951 // imm0_3 predicate - True if the immediate is in the range [0,3]
952 def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
953   return ((uint64_t)Imm) < 4;
954 }]> {
955   let ParserMatchClass = Imm0_3Operand;
958 // imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
959 def imm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
960   return ((uint32_t)Imm) < 8;
961 }]> {
962   let ParserMatchClass = Imm0_7Operand;
965 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
966 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
967   return ((uint32_t)Imm) < 16;
968 }]> {
969   let ParserMatchClass = Imm0_15Operand;
972 // An arithmetic shifter operand:
973 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
974 //  {5-0} - imm6
975 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
976   let PrintMethod = "printShifter";
977   let ParserMatchClass = !cast<AsmOperandClass>(
978                          "ArithmeticShifterOperand" # width);
981 def arith_shift32 : arith_shift<i32, 32>;
982 def arith_shift64 : arith_shift<i64, 64>;
984 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
985     : Operand<Ty>,
986       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
987   let PrintMethod = "printShiftedRegister";
988   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
991 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
992 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
994 def gi_arith_shifted_reg32 :
995   GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
996   GIComplexPatternEquiv<arith_shifted_reg32>;
998 def gi_arith_shifted_reg64 :
999   GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1000   GIComplexPatternEquiv<arith_shifted_reg64>;
1002 // An arithmetic shifter operand:
1003 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1004 //  {5-0} - imm6
1005 class logical_shift<int width> : Operand<i32> {
1006   let PrintMethod = "printShifter";
1007   let ParserMatchClass = !cast<AsmOperandClass>(
1008                          "LogicalShifterOperand" # width);
1011 def logical_shift32 : logical_shift<32>;
1012 def logical_shift64 : logical_shift<64>;
1014 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1015     : Operand<Ty>,
1016       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1017   let PrintMethod = "printShiftedRegister";
1018   let MIOperandInfo = (ops regclass, shiftop);
1021 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1022 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1024 def gi_logical_shifted_reg32 :
1025   GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1026   GIComplexPatternEquiv<logical_shifted_reg32>;
1028 def gi_logical_shifted_reg64 :
1029   GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1030   GIComplexPatternEquiv<logical_shifted_reg64>;
1032 // A logical vector shifter operand:
1033 //  {7-6} - shift type: 00 = lsl
1034 //  {5-0} - imm6: #0, #8, #16, or #24
1035 def logical_vec_shift : Operand<i32> {
1036   let PrintMethod = "printShifter";
1037   let EncoderMethod = "getVecShifterOpValue";
1038   let ParserMatchClass = LogicalVecShifterOperand;
1041 // A logical vector half-word shifter operand:
1042 //  {7-6} - shift type: 00 = lsl
1043 //  {5-0} - imm6: #0 or #8
1044 def logical_vec_hw_shift : Operand<i32> {
1045   let PrintMethod = "printShifter";
1046   let EncoderMethod = "getVecShifterOpValue";
1047   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1050 // A vector move shifter operand:
1051 //  {0} - imm1: #8 or #16
1052 def move_vec_shift : Operand<i32> {
1053   let PrintMethod = "printShifter";
1054   let EncoderMethod = "getMoveVecShifterOpValue";
1055   let ParserMatchClass = MoveVecShifterOperand;
1058 let DiagnosticType = "AddSubSecondSource" in {
1059   def AddSubImmOperand : AsmOperandClass {
1060     let Name = "AddSubImm";
1061     let ParserMethod = "tryParseImmWithOptionalShift";
1062     let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1063   }
1064   def AddSubImmNegOperand : AsmOperandClass {
1065     let Name = "AddSubImmNeg";
1066     let ParserMethod = "tryParseImmWithOptionalShift";
1067     let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1068   }
1070 // An ADD/SUB immediate shifter operand:
1071 //  second operand:
1072 //  {7-6} - shift type: 00 = lsl
1073 //  {5-0} - imm6: #0 or #12
1074 class addsub_shifted_imm<ValueType Ty>
1075     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1076   let PrintMethod = "printAddSubImm";
1077   let EncoderMethod = "getAddSubImmOpValue";
1078   let ParserMatchClass = AddSubImmOperand;
1079   let MIOperandInfo = (ops i32imm, i32imm);
1082 class addsub_shifted_imm_neg<ValueType Ty>
1083     : Operand<Ty> {
1084   let EncoderMethod = "getAddSubImmOpValue";
1085   let ParserMatchClass = AddSubImmNegOperand;
1086   let MIOperandInfo = (ops i32imm, i32imm);
1089 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1090 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1091 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1092 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1094 def gi_addsub_shifted_imm32 :
1095     GIComplexOperandMatcher<s32, "selectArithImmed">,
1096     GIComplexPatternEquiv<addsub_shifted_imm32>;
1098 def gi_addsub_shifted_imm64 :
1099     GIComplexOperandMatcher<s64, "selectArithImmed">,
1100     GIComplexPatternEquiv<addsub_shifted_imm64>;
1102 class neg_addsub_shifted_imm<ValueType Ty>
1103     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1104   let PrintMethod = "printAddSubImm";
1105   let EncoderMethod = "getAddSubImmOpValue";
1106   let ParserMatchClass = AddSubImmOperand;
1107   let MIOperandInfo = (ops i32imm, i32imm);
1110 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1111 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1113 def gi_neg_addsub_shifted_imm32 :
1114     GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1115     GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1117 def gi_neg_addsub_shifted_imm64 :
1118     GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1119     GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1121 // An extend operand:
1122 //  {5-3} - extend type
1123 //  {2-0} - imm3
1124 def arith_extend : Operand<i32> {
1125   let PrintMethod = "printArithExtend";
1126   let ParserMatchClass = ExtendOperand;
1128 def arith_extend64 : Operand<i32> {
1129   let PrintMethod = "printArithExtend";
1130   let ParserMatchClass = ExtendOperand64;
1133 // 'extend' that's a lsl of a 64-bit register.
1134 def arith_extendlsl64 : Operand<i32> {
1135   let PrintMethod = "printArithExtend";
1136   let ParserMatchClass = ExtendOperandLSL64;
1139 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1140                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1141   let PrintMethod = "printExtendedRegister";
1142   let MIOperandInfo = (ops GPR32, arith_extend);
1145 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1146                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1147   let PrintMethod = "printExtendedRegister";
1148   let MIOperandInfo = (ops GPR32, arith_extend64);
1151 def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1152 def gi_arith_extended_reg32_i32 :
1153     GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1154     GIComplexPatternEquiv<arith_extended_reg32_i32>;
1156 def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1157 def gi_arith_extended_reg32_i64 :
1158     GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1159     GIComplexPatternEquiv<arith_extended_reg32_i64>;
1161 def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1162 def gi_arith_extended_reg32to64_i64 :
1163     GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1164     GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1166 // Floating-point immediate.
1168 def fpimm16XForm : SDNodeXForm<fpimm, [{
1169       APFloat InVal = N->getValueAPF();
1170       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1171       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1172     }]>;
1174 def fpimm32XForm : SDNodeXForm<fpimm, [{
1175       APFloat InVal = N->getValueAPF();
1176       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1177       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1178     }]>;
1180 def fpimm64XForm : SDNodeXForm<fpimm, [{
1181       APFloat InVal = N->getValueAPF();
1182       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1183       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1184     }]>;
1186 def fpimm16 : Operand<f16>,
1187               FPImmLeaf<f16, [{
1188       return AArch64_AM::getFP16Imm(Imm) != -1;
1189     }], fpimm16XForm> {
1190   let ParserMatchClass = FPImmOperand;
1191   let PrintMethod = "printFPImmOperand";
1194 def fpimm32 : Operand<f32>,
1195               FPImmLeaf<f32, [{
1196       return AArch64_AM::getFP32Imm(Imm) != -1;
1197     }], fpimm32XForm> {
1198   let ParserMatchClass = FPImmOperand;
1199   let PrintMethod = "printFPImmOperand";
1201 def fpimm64 : Operand<f64>,
1202               FPImmLeaf<f64, [{
1203       return AArch64_AM::getFP64Imm(Imm) != -1;
1204     }], fpimm64XForm> {
1205   let ParserMatchClass = FPImmOperand;
1206   let PrintMethod = "printFPImmOperand";
1209 def fpimm8 : Operand<i32> {
1210   let ParserMatchClass = FPImmOperand;
1211   let PrintMethod = "printFPImmOperand";
1214 def fpimm0 : FPImmLeaf<fAny, [{
1215   return Imm.isExactlyValue(+0.0);
1216 }]>;
1218 def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1219   GISDNodeXFormEquiv<fpimm16XForm>;
1220 def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1221   GISDNodeXFormEquiv<fpimm32XForm>;
1222 def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1223   GISDNodeXFormEquiv<fpimm64XForm>;
1225 // Vector lane operands
1226 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1227   let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1228   let DiagnosticType = "Invalid" # Name;
1229   let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1230   let RenderMethod = "addVectorIndexOperands";
1233 class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1234     : Operand<ty> {
1235   let ParserMatchClass = mc;
1236   let PrintMethod = "printVectorIndex";
1239 multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1240   def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1241   def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1244 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1245 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1246 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1247 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1248 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1250 defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1251                                 [{ return ((uint64_t)Imm) == 1; }]>;
1252 defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1253                                 [{ return ((uint64_t)Imm) < 16; }]>;
1254 defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1255                                 [{ return ((uint64_t)Imm) < 8; }]>;
1256 defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1257                                 [{ return ((uint64_t)Imm) < 4; }]>;
1258 defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1259                                 [{ return ((uint64_t)Imm) < 2; }]>;
1261 defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1262                                    [{ return ((uint64_t)Imm) == 1; }]>;
1263 defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1264                                    [{ return ((uint64_t)Imm) < 16; }]>;
1265 defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1266                                    [{ return ((uint64_t)Imm) < 8; }]>;
1267 defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1268                                    [{ return ((uint64_t)Imm) < 4; }]>;
1269 defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1270                                    [{ return ((uint64_t)Imm) < 2; }]>;
1272 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1273 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1274 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1275 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1276 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1278 defm sve_elm_idx_extdup_b
1279   : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1280                 [{ return ((uint64_t)Imm) < 64; }]>;
1281 defm sve_elm_idx_extdup_h
1282   : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1283                 [{ return ((uint64_t)Imm) < 32; }]>;
1284 defm sve_elm_idx_extdup_s
1285   : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1286                 [{ return ((uint64_t)Imm) < 16; }]>;
1287 defm sve_elm_idx_extdup_d
1288   : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1289                 [{ return ((uint64_t)Imm) < 8; }]>;
1290 defm sve_elm_idx_extdup_q
1291   : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1292                 [{ return ((uint64_t)Imm) < 4; }]>;
1294 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1295 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1296 // are encoded as the eight bit value 'abcdefgh'.
1297 def simdimmtype10 : Operand<i32>,
1298                     FPImmLeaf<f64, [{
1299       return AArch64_AM::isAdvSIMDModImmType10(
1300                  Imm.bitcastToAPInt().getZExtValue());
1301     }], SDNodeXForm<fpimm, [{
1302       APFloat InVal = N->getValueAPF();
1303       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1304                                                            .bitcastToAPInt()
1305                                                            .getZExtValue());
1306       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1307     }]>> {
1308   let ParserMatchClass = SIMDImmType10Operand;
1309   let PrintMethod = "printSIMDType10Operand";
1313 //---
1314 // System management
1315 //---
1317 // Base encoding for system instruction operands.
1318 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1319 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1320                   list<dag> pattern = []>
1321     : I<oops, iops, asm, operands, "", pattern> {
1322   let Inst{31-22} = 0b1101010100;
1323   let Inst{21}    = L;
1326 // System instructions which do not have an Rt register.
1327 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1328                     list<dag> pattern = []>
1329     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1330   let Inst{4-0} = 0b11111;
1333 // System instructions which have an Rt register.
1334 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1335                 list<dag> pattern = []>
1336     : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1337       Sched<[WriteSys]> {
1338   bits<5> Rt;
1339   let Inst{4-0} = Rt;
1342 // System instructions for transactional memory extension
1343 class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1344                     string asm, string operands, list<dag> pattern>
1345     : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1346       Sched<[WriteSys]> {
1347   let Inst{20-12} = 0b000110011;
1348   let Inst{11-8} = CRm;
1349   let Inst{7-5} = op2;
1350   let DecoderMethod = "";
1352   let mayLoad = 1;
1353   let mayStore = 1;
1356 // System instructions for transactional memory - single input operand
1357 class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1358     : TMBaseSystemI<0b1, CRm, 0b011,
1359                     (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1360   bits<5> Rt;
1361   let Inst{4-0} = Rt;
1364 // System instructions that pass a register argument
1365 // This class assumes the register is for input rather than output.
1366 class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1367                       list<dag> pattern = []>
1368     : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1369   let Inst{20-12} = 0b000110001;
1370   let Inst{11-8} = CRm;
1371   let Inst{7-5} = Op2;
1374 // System instructions for transactional memory - no operand
1375 class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1376     : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1377   let Inst{4-0} = 0b11111;
1380 // System instructions for exit from transactions
1381 class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1382     : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1383       Sched<[WriteSys]> {
1384   bits<16> imm;
1385   let Inst{31-24} = 0b11010100;
1386   let Inst{23-21} = op1;
1387   let Inst{20-5}  = imm;
1388   let Inst{4-0}   = 0b00000;
1391 // Hint instructions that take both a CRm and a 3-bit immediate.
1392 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1393 // model patterns with sufficiently fine granularity
1394 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1395   class HintI<string mnemonic>
1396       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1397                       [(int_aarch64_hint imm0_127:$imm)]>,
1398         Sched<[WriteHint]> {
1399     bits <7> imm;
1400     let Inst{20-12} = 0b000110010;
1401     let Inst{11-5} = imm;
1402   }
1404 // System instructions taking a single literal operand which encodes into
1405 // CRm. op2 differentiates the opcodes.
1406 def BarrierAsmOperand : AsmOperandClass {
1407   let Name = "Barrier";
1408   let ParserMethod = "tryParseBarrierOperand";
1410 def barrier_op : Operand<i32> {
1411   let PrintMethod = "printBarrierOption";
1412   let ParserMatchClass = BarrierAsmOperand;
1414 def BarriernXSAsmOperand : AsmOperandClass {
1415   let Name = "BarriernXS";
1416   let ParserMethod = "tryParseBarriernXSOperand";
1418 def barrier_nxs_op : Operand<i32> {
1419   let PrintMethod = "printBarriernXSOption";
1420   let ParserMatchClass = BarriernXSAsmOperand;
1422 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1423                  list<dag> pattern = []>
1424     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1425       Sched<[WriteBarrier]> {
1426   bits<4> CRm;
1427   let Inst{20-12} = 0b000110011;
1428   let Inst{11-8} = CRm;
1429   let Inst{7-5} = opc;
1432 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1433     : SimpleSystemI<0, (ins), asm, "", pattern>,
1434       Sched<[]> {
1435   bits<4> CRm;
1436   let CRm = 0b0011;
1437   let Inst{31-12} = 0b11010101000000110010;
1438   let Inst{11-8} = CRm;
1439   let Inst{7-5} = op2;
1440   let Inst{4-0} = 0b11111;
1443 // MRS/MSR system instructions. These have different operand classes because
1444 // a different subset of registers can be accessed through each instruction.
1445 def MRSSystemRegisterOperand : AsmOperandClass {
1446   let Name = "MRSSystemRegister";
1447   let ParserMethod = "tryParseSysReg";
1448   let DiagnosticType = "MRS";
1450 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1451 def mrs_sysreg_op : Operand<i32> {
1452   let ParserMatchClass = MRSSystemRegisterOperand;
1453   let DecoderMethod = "DecodeMRSSystemRegister";
1454   let PrintMethod = "printMRSSystemRegister";
1457 def MSRSystemRegisterOperand : AsmOperandClass {
1458   let Name = "MSRSystemRegister";
1459   let ParserMethod = "tryParseSysReg";
1460   let DiagnosticType = "MSR";
1462 def msr_sysreg_op : Operand<i32> {
1463   let ParserMatchClass = MSRSystemRegisterOperand;
1464   let DecoderMethod = "DecodeMSRSystemRegister";
1465   let PrintMethod = "printMSRSystemRegister";
1468 def PSBHintOperand : AsmOperandClass {
1469   let Name = "PSBHint";
1470   let ParserMethod = "tryParsePSBHint";
1472 def psbhint_op : Operand<i32> {
1473   let ParserMatchClass = PSBHintOperand;
1474   let PrintMethod = "printPSBHintOp";
1475   let MCOperandPredicate = [{
1476     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1477     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1478     if (!MCOp.isImm())
1479       return false;
1480     return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1481   }];
1484 def BTIHintOperand : AsmOperandClass {
1485   let Name = "BTIHint";
1486   let ParserMethod = "tryParseBTIHint";
1488 def btihint_op : Operand<i32> {
1489   let ParserMatchClass = BTIHintOperand;
1490   let PrintMethod = "printBTIHintOp";
1491   let MCOperandPredicate = [{
1492     // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1493     if (!MCOp.isImm())
1494       return false;
1495     return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1496   }];
1499 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1500                        "mrs", "\t$Rt, $systemreg"> {
1501   bits<16> systemreg;
1502   let Inst{20-5} = systemreg;
1503   let DecoderNamespace = "Fallback";
1504   // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1505   // require doing this. The alternative was to explicitly model each one, but
1506   // it feels like it is unnecessary because it seems there are no negative
1507   // consequences setting these flags for all.
1508   let Defs = [NZCV];
1511 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1512 // Explicitly modeling each of the system register as a register class
1513 // would do it, but feels like overkill at this point.
1514 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1515                        "msr", "\t$systemreg, $Rt"> {
1516   bits<16> systemreg;
1517   let Inst{20-5} = systemreg;
1518   let DecoderNamespace = "Fallback";
1521 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1522   let Name = "SystemPStateFieldWithImm0_15";
1523   let ParserMethod = "tryParseSysReg";
1525 def pstatefield4_op : Operand<i32> {
1526   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1527   let PrintMethod = "printSystemPStateField";
1530 // Instructions to modify PSTATE, no input reg
1531 let Defs = [NZCV] in
1532 class PstateWriteSimple<dag iops, string asm, string operands>
1533   : SimpleSystemI<0, iops, asm, operands> {
1535   let Inst{20-19} = 0b00;
1536   let Inst{15-12} = 0b0100;
1539 class MSRpstateImm0_15
1540   : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1541                   "\t$pstatefield, $imm">,
1542     Sched<[WriteSys]> {
1544   bits<6> pstatefield;
1545   bits<4> imm;
1546   let Inst{18-16} = pstatefield{5-3};
1547   let Inst{11-8} = imm;
1548   let Inst{7-5} = pstatefield{2-0};
1550   let DecoderMethod = "DecodeSystemPStateInstruction";
1551   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1552   // Fail the decoder should attempt to decode the instruction as MSRI.
1553   let hasCompleteDecoder = 0;
1556 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1557   let Name = "SystemPStateFieldWithImm0_1";
1558   let ParserMethod = "tryParseSysReg";
1560 def pstatefield1_op : Operand<i32> {
1561   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1562   let PrintMethod = "printSystemPStateField";
1565 class MSRpstateImm0_1
1566   : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1567                  "\t$pstatefield, $imm">,
1568     Sched<[WriteSys]> {
1570   bits<6> pstatefield;
1571   bit imm;
1572   let Inst{18-16} = pstatefield{5-3};
1573   let Inst{11-9} = 0b000;
1574   let Inst{8} = imm;
1575   let Inst{7-5} = pstatefield{2-0};
1577   let DecoderMethod = "DecodeSystemPStateInstruction";
1578   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1579   // Fail the decoder should attempt to decode the instruction as MSRI.
1580   let hasCompleteDecoder = 0;
1583 // SYS and SYSL generic system instructions.
1584 def SysCRAsmOperand : AsmOperandClass {
1585   let Name = "SysCR";
1586   let ParserMethod = "tryParseSysCROperand";
1589 def sys_cr_op : Operand<i32> {
1590   let PrintMethod = "printSysCROperand";
1591   let ParserMatchClass = SysCRAsmOperand;
1594 class SystemXtI<bit L, string asm>
1595   : RtSystemI<L, (outs),
1596        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1597        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1598   bits<3> op1;
1599   bits<4> Cn;
1600   bits<4> Cm;
1601   bits<3> op2;
1602   let Inst{20-19} = 0b01;
1603   let Inst{18-16} = op1;
1604   let Inst{15-12} = Cn;
1605   let Inst{11-8}  = Cm;
1606   let Inst{7-5}   = op2;
1609 class SystemLXtI<bit L, string asm>
1610   : RtSystemI<L, (outs),
1611        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1612        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1613   bits<3> op1;
1614   bits<4> Cn;
1615   bits<4> Cm;
1616   bits<3> op2;
1617   let Inst{20-19} = 0b01;
1618   let Inst{18-16} = op1;
1619   let Inst{15-12} = Cn;
1620   let Inst{11-8}  = Cm;
1621   let Inst{7-5}   = op2;
1625 // Branch (register) instructions:
1627 //  case opc of
1628 //    0001 blr
1629 //    0000 br
1630 //    0101 dret
1631 //    0100 eret
1632 //    0010 ret
1633 //    otherwise UNDEFINED
1634 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1635                     string operands, list<dag> pattern>
1636     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1637   let Inst{31-25} = 0b1101011;
1638   let Inst{24-21} = opc;
1639   let Inst{20-16} = 0b11111;
1640   let Inst{15-10} = 0b000000;
1641   let Inst{4-0}   = 0b00000;
1644 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1645     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1646   bits<5> Rn;
1647   let Inst{9-5} = Rn;
1650 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1651 class SpecialReturn<bits<4> opc, string asm>
1652     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1653   let Inst{9-5} = 0b11111;
1656 let mayLoad = 1 in
1657 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1658   : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1659   Sched<[]> {
1660   bits<5> Rn;
1661   bits<5> Rt;
1662   let Inst{31-30} = sz;
1663   let Inst{29-10} = 0b11100010111111110000;
1664   let Inst{9-5} = Rn;
1665   let Inst{4-0} = Rt;
1668 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1669                list<dag> pattern>
1670   : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1671   let isAuthenticated = 1;
1672   let Inst{31-25} = 0b1101011;
1673   let Inst{20-11} = 0b1111100001;
1674   let Inst{10} = M;
1675   let Inst{4-0} = 0b11111;
1678 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1679   : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1680   bits<5> Rn;
1681   bits<5> Rm;
1682   let Inst{24-22} = 0b100;
1683   let Inst{21} = op;
1684   let Inst{9-5} = Rn;
1685   let Inst{4-0} = Rm;
1688 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1689   : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1690   bits<5> Rn;
1691   let Inst{24} = 0;
1692   let Inst{23-21} = opc;
1693   let Inst{9-5} = Rn;
1696 let Uses = [LR,SP] in
1697 class AuthReturn<bits<3> op, bits<1> M, string asm>
1698   : AuthBase<M, (outs), (ins), asm, "", []> {
1699   let Inst{24} = 0;
1700   let Inst{23-21} = op;
1701   let Inst{9-0} = 0b1111111111;
1704 let mayLoad = 1 in
1705 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1706                    string operands, string cstr, Operand opr>
1707   : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1708   bits<10> offset;
1709   bits<5> Rn;
1710   bits<5> Rt;
1711   let isAuthenticated = 1;
1712   let Inst{31-24} = 0b11111000;
1713   let Inst{23} = M;
1714   let Inst{22} = offset{9};
1715   let Inst{21} = 1;
1716   let Inst{20-12} = offset{8-0};
1717   let Inst{11} = W;
1718   let Inst{10} = 1;
1719   let Inst{9-5} = Rn;
1720   let Inst{4-0} = Rt;
1722   let DecoderMethod = "DecodeAuthLoadInstruction";
1725 multiclass AuthLoad<bit M, string asm, Operand opr> {
1726   def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1727                                (ins GPR64sp:$Rn, opr:$offset),
1728                                asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1729   def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1730                                (ins GPR64sp:$Rn, opr:$offset),
1731                                asm, "\t$Rt, [$Rn, $offset]!",
1732                                "$Rn = $wback,@earlyclobber $wback", opr>;
1734   def : InstAlias<asm # "\t$Rt, [$Rn]",
1735                   (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1737   def : InstAlias<asm # "\t$Rt, [$wback]!",
1738                   (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1741 //---
1742 // Conditional branch instruction.
1743 //---
1745 // Condition code.
1746 // 4-bit immediate. Pretty-printed as <cc>
1747 def ccode : Operand<i32> {
1748   let PrintMethod = "printCondCode";
1749   let ParserMatchClass = CondCode;
1751 def inv_ccode : Operand<i32> {
1752   // AL and NV are invalid in the aliases which use inv_ccode
1753   let PrintMethod = "printInverseCondCode";
1754   let ParserMatchClass = CondCode;
1755   let MCOperandPredicate = [{
1756     return MCOp.isImm() &&
1757            MCOp.getImm() != AArch64CC::AL &&
1758            MCOp.getImm() != AArch64CC::NV;
1759   }];
1762 // Conditional branch target. 19-bit immediate. The low two bits of the target
1763 // offset are implied zero and so are not part of the immediate.
1764 def am_brcond : Operand<OtherVT> {
1765   let EncoderMethod = "getCondBranchTargetOpValue";
1766   let DecoderMethod = "DecodePCRelLabel19";
1767   let PrintMethod = "printAlignedLabel";
1768   let ParserMatchClass = PCRelLabel19Operand;
1769   let OperandType = "OPERAND_PCREL";
1772 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1773                      "b", ".$cond\t$target", "",
1774                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1775                    Sched<[WriteBr]> {
1776   let isBranch = 1;
1777   let isTerminator = 1;
1778   let Uses = [NZCV];
1780   bits<4> cond;
1781   bits<19> target;
1782   let Inst{31-24} = 0b01010100;
1783   let Inst{23-5} = target;
1784   let Inst{4} = 0;
1785   let Inst{3-0} = cond;
1788 //---
1789 // Compare-and-branch instructions.
1790 //---
1791 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1792     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1793          asm, "\t$Rt, $target", "",
1794          [(node regtype:$Rt, bb:$target)]>,
1795       Sched<[WriteBr]> {
1796   let isBranch = 1;
1797   let isTerminator = 1;
1799   bits<5> Rt;
1800   bits<19> target;
1801   let Inst{30-25} = 0b011010;
1802   let Inst{24}    = op;
1803   let Inst{23-5}  = target;
1804   let Inst{4-0}   = Rt;
1807 multiclass CmpBranch<bit op, string asm, SDNode node> {
1808   def W : BaseCmpBranch<GPR32, op, asm, node> {
1809     let Inst{31} = 0;
1810   }
1811   def X : BaseCmpBranch<GPR64, op, asm, node> {
1812     let Inst{31} = 1;
1813   }
1816 //---
1817 // Test-bit-and-branch instructions.
1818 //---
1819 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1820 // the target offset are implied zero and so are not part of the immediate.
1821 def am_tbrcond : Operand<OtherVT> {
1822   let EncoderMethod = "getTestBranchTargetOpValue";
1823   let PrintMethod = "printAlignedLabel";
1824   let ParserMatchClass = BranchTarget14Operand;
1825   let OperandType = "OPERAND_PCREL";
1828 // AsmOperand classes to emit (or not) special diagnostics
1829 def TBZImm0_31Operand : AsmOperandClass {
1830   let Name = "TBZImm0_31";
1831   let PredicateMethod = "isImmInRange<0,31>";
1832   let RenderMethod = "addImmOperands";
1834 def TBZImm32_63Operand : AsmOperandClass {
1835   let Name = "Imm32_63";
1836   let PredicateMethod = "isImmInRange<32,63>";
1837   let DiagnosticType = "InvalidImm0_63";
1838   let RenderMethod = "addImmOperands";
1841 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1842   return (((uint32_t)Imm) < 32);
1843 }]> {
1844   let ParserMatchClass = matcher;
1847 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1848 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1850 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1851   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1852 }]> {
1853   let ParserMatchClass = TBZImm32_63Operand;
1856 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1857                      bit op, string asm, SDNode node>
1858     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1859        asm, "\t$Rt, $bit_off, $target", "",
1860        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1861       Sched<[WriteBr]> {
1862   let isBranch = 1;
1863   let isTerminator = 1;
1865   bits<5> Rt;
1866   bits<6> bit_off;
1867   bits<14> target;
1869   let Inst{30-25} = 0b011011;
1870   let Inst{24}    = op;
1871   let Inst{23-19} = bit_off{4-0};
1872   let Inst{18-5}  = target;
1873   let Inst{4-0}   = Rt;
1875   let DecoderMethod = "DecodeTestAndBranch";
1878 multiclass TestBranch<bit op, string asm, SDNode node> {
1879   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1880     let Inst{31} = 0;
1881   }
1883   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1884     let Inst{31} = 1;
1885   }
1887   // Alias X-reg with 0-31 imm to W-Reg.
1888   def : InstAlias<asm # "\t$Rd, $imm, $target",
1889                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1890                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1891   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1892             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1893             tbz_imm0_31_diag:$imm, bb:$target)>;
1896 //---
1897 // Unconditional branch (immediate) instructions.
1898 //---
1899 def am_b_target : Operand<OtherVT> {
1900   let EncoderMethod = "getBranchTargetOpValue";
1901   let PrintMethod = "printAlignedLabel";
1902   let ParserMatchClass = BranchTarget26Operand;
1903   let OperandType = "OPERAND_PCREL";
1905 def am_bl_target : Operand<i64> {
1906   let EncoderMethod = "getBranchTargetOpValue";
1907   let PrintMethod = "printAlignedLabel";
1908   let ParserMatchClass = BranchTarget26Operand;
1909   let OperandType = "OPERAND_PCREL";
1912 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1913     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1914   bits<26> addr;
1915   let Inst{31}    = op;
1916   let Inst{30-26} = 0b00101;
1917   let Inst{25-0}  = addr;
1919   let DecoderMethod = "DecodeUnconditionalBranch";
1922 class BranchImm<bit op, string asm, list<dag> pattern>
1923     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1924 class CallImm<bit op, string asm, list<dag> pattern>
1925     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1927 //---
1928 // Basic one-operand data processing instructions.
1929 //---
1931 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1932 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1933                          SDPatternOperator node>
1934   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1935       [(set regtype:$Rd, (node regtype:$Rn))]>,
1936     Sched<[WriteI, ReadI]> {
1937   bits<5> Rd;
1938   bits<5> Rn;
1940   let Inst{30-13} = 0b101101011000000000;
1941   let Inst{12-10} = opc;
1942   let Inst{9-5}   = Rn;
1943   let Inst{4-0}   = Rd;
1946 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1947 multiclass OneOperandData<bits<3> opc, string asm,
1948                           SDPatternOperator node = null_frag> {
1949   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1950     let Inst{31} = 0;
1951   }
1953   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1954     let Inst{31} = 1;
1955   }
1958 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1959     : BaseOneOperandData<opc, GPR32, asm, node> {
1960   let Inst{31} = 0;
1963 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1964     : BaseOneOperandData<opc, GPR64, asm, node> {
1965   let Inst{31} = 1;
1968 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1969   : I<(outs GPR64:$Rd), (ins GPR64:$src, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
1970       "$Rd = $src",
1971       []>,
1972     Sched<[WriteI, ReadI]> {
1973   bits<5> Rd;
1974   bits<5> Rn;
1975   let Inst{31-15} = 0b11011010110000010;
1976   let Inst{14-12} = opcode_prefix;
1977   let Inst{11-10} = opcode;
1978   let Inst{9-5} = Rn;
1979   let Inst{4-0} = Rd;
1982 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1983   : I<(outs GPR64:$Rd), (ins GPR64:$src), asm, "\t$Rd", "$Rd = $src",
1984       []>, Sched<[]> {
1985   bits<5> Rd;
1986   let Inst{31-15} = 0b11011010110000010;
1987   let Inst{14-12} = opcode_prefix;
1988   let Inst{11-10} = opcode;
1989   let Inst{9-5} = 0b11111;
1990   let Inst{4-0} = Rd;
1993 class SignAuthTwoOperand<bits<4> opc, string asm,
1994                          SDPatternOperator OpNode>
1995   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1996       asm, "\t$Rd, $Rn, $Rm", "",
1997       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1998     Sched<[WriteI, ReadI, ReadI]> {
1999   bits<5> Rd;
2000   bits<5> Rn;
2001   bits<5> Rm;
2002   let Inst{31-21} = 0b10011010110;
2003   let Inst{20-16} = Rm;
2004   let Inst{15-14} = 0b00;
2005   let Inst{13-10} = opc;
2006   let Inst{9-5}   = Rn;
2007   let Inst{4-0}   = Rd;
2010 class ClearAuth<bits<1> data, string asm>
2011   : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2012   bits<5> Rd;
2013   let Inst{31-11} = 0b110110101100000101000;
2014   let Inst{10} = data;
2015   let Inst{9-5} = 0b11111;
2016   let Inst{4-0} = Rd;
2019 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2020 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2021     : I<(outs), iops, asm, ops, "", []>,
2022       Sched<[WriteI, ReadI, ReadI]> {
2023   let Uses = [NZCV];
2024   let Defs = [NZCV];
2025   bits<5> Rn;
2026   let Inst{31}    = sf;
2027   let Inst{30-15} = 0b0111010000000000;
2028   let Inst{14}    = sz;
2029   let Inst{13-10} = 0b0010;
2030   let Inst{9-5}   = Rn;
2031   let Inst{4-0}   = 0b01101;
2034 class FlagRotate<dag iops, string asm, string ops>
2035     : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2036   bits<6> imm;
2037   bits<4> mask;
2038   let Inst{20-15} = imm;
2039   let Inst{13-10} = 0b0001;
2040   let Inst{4}     = 0b0;
2041   let Inst{3-0}   = mask;
2044 //---
2045 // Basic two-operand data processing instructions.
2046 //---
2047 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2048                           list<dag> pattern>
2049     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2050         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2051       Sched<[WriteI, ReadI, ReadI]> {
2052   let Uses = [NZCV];
2053   bits<5> Rd;
2054   bits<5> Rn;
2055   bits<5> Rm;
2056   let Inst{30}    = isSub;
2057   let Inst{28-21} = 0b11010000;
2058   let Inst{20-16} = Rm;
2059   let Inst{15-10} = 0;
2060   let Inst{9-5}   = Rn;
2061   let Inst{4-0}   = Rd;
2064 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2065                       SDNode OpNode>
2066     : BaseBaseAddSubCarry<isSub, regtype, asm,
2067         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2069 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2070                               SDNode OpNode>
2071     : BaseBaseAddSubCarry<isSub, regtype, asm,
2072         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2073          (implicit NZCV)]> {
2074   let Defs = [NZCV];
2077 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2078                        SDNode OpNode, SDNode OpNode_setflags> {
2079   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2080     let Inst{31} = 0;
2081     let Inst{29} = 0;
2082   }
2083   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2084     let Inst{31} = 1;
2085     let Inst{29} = 0;
2086   }
2088   // Sets flags.
2089   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2090                                     OpNode_setflags> {
2091     let Inst{31} = 0;
2092     let Inst{29} = 1;
2093   }
2094   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2095                                     OpNode_setflags> {
2096     let Inst{31} = 1;
2097     let Inst{29} = 1;
2098   }
2101 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2102                      SDPatternOperator OpNode,
2103                      RegisterClass in1regtype = regtype,
2104                      RegisterClass in2regtype = regtype>
2105   : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2106       asm, "\t$Rd, $Rn, $Rm", "",
2107       [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2108   bits<5> Rd;
2109   bits<5> Rn;
2110   bits<5> Rm;
2111   let Inst{30-21} = 0b0011010110;
2112   let Inst{20-16} = Rm;
2113   let Inst{15-14} = 0b00;
2114   let Inst{13-10} = opc;
2115   let Inst{9-5}   = Rn;
2116   let Inst{4-0}   = Rd;
2119 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2120               SDPatternOperator OpNode>
2121     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2122   let Inst{10}    = isSigned;
2125 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2126   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2127            Sched<[WriteID32, ReadID, ReadID]> {
2128     let Inst{31} = 0;
2129   }
2130   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2131            Sched<[WriteID64, ReadID, ReadID]> {
2132     let Inst{31} = 1;
2133   }
2136 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2137                 SDPatternOperator OpNode = null_frag>
2138   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2139     Sched<[WriteIS, ReadI]> {
2140   let Inst{11-10} = shift_type;
2143 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2144   def Wr : BaseShift<shift_type, GPR32, asm> {
2145     let Inst{31} = 0;
2146   }
2148   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2149     let Inst{31} = 1;
2150   }
2152   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2153             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2154                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2156   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2157             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2159   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2160             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2162   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2163             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2165   def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2166             (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2167                 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2169   def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2170             (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2171                 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2174 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2175     : InstAlias<asm#"\t$dst, $src1, $src2",
2176                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2178 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2179                        RegisterClass addtype, string asm,
2180                        list<dag> pattern>
2181   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2182       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2183   bits<5> Rd;
2184   bits<5> Rn;
2185   bits<5> Rm;
2186   bits<5> Ra;
2187   let Inst{30-24} = 0b0011011;
2188   let Inst{23-21} = opc;
2189   let Inst{20-16} = Rm;
2190   let Inst{15}    = isSub;
2191   let Inst{14-10} = Ra;
2192   let Inst{9-5}   = Rn;
2193   let Inst{4-0}   = Rd;
2196 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
2197   // MADD/MSUB generation is decided by MachineCombiner.cpp
2198   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
2199       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
2200       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2201     let Inst{31} = 0;
2202   }
2204   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
2205       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
2206       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2207     let Inst{31} = 1;
2208   }
2211 class WideMulAccum<bit isSub, bits<3> opc, string asm,
2212                    SDNode AccNode, SDNode ExtNode>
2213   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2214     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2215                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2216     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2217   let Inst{31} = 1;
2220 class MulHi<bits<3> opc, string asm, SDNode OpNode>
2221   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2222       asm, "\t$Rd, $Rn, $Rm", "",
2223       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2224     Sched<[WriteIM64, ReadIM, ReadIM]> {
2225   bits<5> Rd;
2226   bits<5> Rn;
2227   bits<5> Rm;
2228   let Inst{31-24} = 0b10011011;
2229   let Inst{23-21} = opc;
2230   let Inst{20-16} = Rm;
2231   let Inst{15}    = 0;
2232   let Inst{9-5}   = Rn;
2233   let Inst{4-0}   = Rd;
2235   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2236   // (i.e. all bits 1) but is ignored by the processor.
2237   let PostEncoderMethod = "fixMulHigh";
2240 class MulAccumWAlias<string asm, Instruction inst>
2241     : InstAlias<asm#"\t$dst, $src1, $src2",
2242                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2243 class MulAccumXAlias<string asm, Instruction inst>
2244     : InstAlias<asm#"\t$dst, $src1, $src2",
2245                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2246 class WideMulAccumAlias<string asm, Instruction inst>
2247     : InstAlias<asm#"\t$dst, $src1, $src2",
2248                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2250 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2251               SDPatternOperator OpNode, string asm>
2252   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2253       asm, "\t$Rd, $Rn, $Rm", "",
2254       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2255     Sched<[WriteISReg, ReadI, ReadISReg]> {
2256   bits<5> Rd;
2257   bits<5> Rn;
2258   bits<5> Rm;
2260   let Inst{31} = sf;
2261   let Inst{30-21} = 0b0011010110;
2262   let Inst{20-16} = Rm;
2263   let Inst{15-13} = 0b010;
2264   let Inst{12} = C;
2265   let Inst{11-10} = sz;
2266   let Inst{9-5} = Rn;
2267   let Inst{4-0} = Rd;
2268   let Predicates = [HasCRC];
2271 //---
2272 // Address generation.
2273 //---
2275 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2276     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2277         pattern>,
2278       Sched<[WriteI]> {
2279   bits<5>  Xd;
2280   bits<21> label;
2281   let Inst{31}    = page;
2282   let Inst{30-29} = label{1-0};
2283   let Inst{28-24} = 0b10000;
2284   let Inst{23-5}  = label{20-2};
2285   let Inst{4-0}   = Xd;
2287   let DecoderMethod = "DecodeAdrInstruction";
2290 //---
2291 // Move immediate.
2292 //---
2294 def movimm32_imm : Operand<i32> {
2295   let ParserMatchClass = AsmImmRange<0, 65535>;
2296   let EncoderMethod = "getMoveWideImmOpValue";
2297   let PrintMethod = "printImm";
2299 def movimm32_shift : Operand<i32> {
2300   let PrintMethod = "printShifter";
2301   let ParserMatchClass = MovImm32ShifterOperand;
2303 def movimm64_shift : Operand<i32> {
2304   let PrintMethod = "printShifter";
2305   let ParserMatchClass = MovImm64ShifterOperand;
2308 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2309 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2310                         string asm>
2311   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2312        asm, "\t$Rd, $imm$shift", "", []>,
2313     Sched<[WriteImm]> {
2314   bits<5> Rd;
2315   bits<16> imm;
2316   bits<6> shift;
2317   let Inst{30-29} = opc;
2318   let Inst{28-23} = 0b100101;
2319   let Inst{22-21} = shift{5-4};
2320   let Inst{20-5}  = imm;
2321   let Inst{4-0}   = Rd;
2323   let DecoderMethod = "DecodeMoveImmInstruction";
2326 multiclass MoveImmediate<bits<2> opc, string asm> {
2327   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2328     let Inst{31} = 0;
2329   }
2331   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2332     let Inst{31} = 1;
2333   }
2336 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2337 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2338                           string asm>
2339   : I<(outs regtype:$Rd),
2340       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2341        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2342     Sched<[WriteI, ReadI]> {
2343   bits<5> Rd;
2344   bits<16> imm;
2345   bits<6> shift;
2346   let Inst{30-29} = opc;
2347   let Inst{28-23} = 0b100101;
2348   let Inst{22-21} = shift{5-4};
2349   let Inst{20-5}  = imm;
2350   let Inst{4-0}   = Rd;
2352   let DecoderMethod = "DecodeMoveImmInstruction";
2355 multiclass InsertImmediate<bits<2> opc, string asm> {
2356   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2357     let Inst{31} = 0;
2358   }
2360   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2361     let Inst{31} = 1;
2362   }
2365 //---
2366 // Add/Subtract
2367 //---
2369 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2370                     string asm_inst, string asm_ops,
2371                     dag inputs, dag pattern>
2372     : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2373       Sched<[WriteI, ReadI]> {
2374   bits<5>  Rd;
2375   bits<5>  Rn;
2376   let Inst{30}    = isSub;
2377   let Inst{29}    = setFlags;
2378   let Inst{28-24} = 0b10001;
2379   let Inst{9-5}   = Rn;
2380   let Inst{4-0}   = Rd;
2383 class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2384                      RegisterClass srcRegtype, addsub_shifted_imm immtype,
2385                      string asm_inst, SDPatternOperator OpNode>
2386     : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2387                     (ins srcRegtype:$Rn, immtype:$imm),
2388                     (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2389   bits<14> imm;
2390   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2391   let Inst{21-10} = imm{11-0};
2392   let DecoderMethod = "DecodeAddSubImmShift";
2395 class BaseAddSubRegPseudo<RegisterClass regtype,
2396                           SDPatternOperator OpNode>
2397     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2398              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2399       Sched<[WriteI, ReadI, ReadI]>;
2401 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2402                      arith_shifted_reg shifted_regtype, string asm,
2403                      SDPatternOperator OpNode>
2404     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2405         asm, "\t$Rd, $Rn, $Rm", "",
2406         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2407       Sched<[WriteISReg, ReadI, ReadISReg]> {
2408   // The operands are in order to match the 'addr' MI operands, so we
2409   // don't need an encoder method and by-name matching. Just use the default
2410   // in-order handling. Since we're using by-order, make sure the names
2411   // do not match.
2412   bits<5> dst;
2413   bits<5> src1;
2414   bits<5> src2;
2415   bits<8> shift;
2416   let Inst{30}    = isSub;
2417   let Inst{29}    = setFlags;
2418   let Inst{28-24} = 0b01011;
2419   let Inst{23-22} = shift{7-6};
2420   let Inst{21}    = 0;
2421   let Inst{20-16} = src2;
2422   let Inst{15-10} = shift{5-0};
2423   let Inst{9-5}   = src1;
2424   let Inst{4-0}   = dst;
2426   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2429 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2430                      RegisterClass src1Regtype, Operand src2Regtype,
2431                      string asm, SDPatternOperator OpNode>
2432     : I<(outs dstRegtype:$R1),
2433         (ins src1Regtype:$R2, src2Regtype:$R3),
2434         asm, "\t$R1, $R2, $R3", "",
2435         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2436       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2437   bits<5> Rd;
2438   bits<5> Rn;
2439   bits<5> Rm;
2440   bits<6> ext;
2441   let Inst{30}    = isSub;
2442   let Inst{29}    = setFlags;
2443   let Inst{28-24} = 0b01011;
2444   let Inst{23-21} = 0b001;
2445   let Inst{20-16} = Rm;
2446   let Inst{15-13} = ext{5-3};
2447   let Inst{12-10} = ext{2-0};
2448   let Inst{9-5}   = Rn;
2449   let Inst{4-0}   = Rd;
2451   let DecoderMethod = "DecodeAddSubERegInstruction";
2454 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2455 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2456                        RegisterClass src1Regtype, RegisterClass src2Regtype,
2457                        Operand ext_op, string asm>
2458     : I<(outs dstRegtype:$Rd),
2459         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2460         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2461       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2462   bits<5> Rd;
2463   bits<5> Rn;
2464   bits<5> Rm;
2465   bits<6> ext;
2466   let Inst{30}    = isSub;
2467   let Inst{29}    = setFlags;
2468   let Inst{28-24} = 0b01011;
2469   let Inst{23-21} = 0b001;
2470   let Inst{20-16} = Rm;
2471   let Inst{15}    = ext{5};
2472   let Inst{12-10} = ext{2-0};
2473   let Inst{9-5}   = Rn;
2474   let Inst{4-0}   = Rd;
2476   let DecoderMethod = "DecodeAddSubERegInstruction";
2479 // Aliases for register+register add/subtract.
2480 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2481                      RegisterClass src1Regtype, RegisterClass src2Regtype,
2482                      int shiftExt>
2483     : InstAlias<asm#"\t$dst, $src1, $src2",
2484                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2485                       shiftExt)>;
2487 multiclass AddSub<bit isSub, string mnemonic, string alias,
2488                   SDPatternOperator OpNode = null_frag> {
2489   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2490   // Add/Subtract immediate
2491   // Increase the weight of the immediate variant to try to match it before
2492   // the extended register variant.
2493   // We used to match the register variant before the immediate when the
2494   // register argument could be implicitly zero-extended.
2495   let AddedComplexity = 6 in
2496   def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2497                            mnemonic, OpNode> {
2498     let Inst{31} = 0;
2499   }
2500   let AddedComplexity = 6 in
2501   def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2502                            mnemonic, OpNode> {
2503     let Inst{31} = 1;
2504   }
2506   // Add/Subtract register - Only used for CodeGen
2507   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2508   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2510   // Add/Subtract shifted register
2511   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2512                            OpNode> {
2513     let Inst{31} = 0;
2514   }
2515   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2516                            OpNode> {
2517     let Inst{31} = 1;
2518   }
2519   }
2521   // Add/Subtract extended register
2522   let AddedComplexity = 1, hasSideEffects = 0 in {
2523   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2524                            arith_extended_reg32_i32, mnemonic, OpNode> {
2525     let Inst{31} = 0;
2526   }
2527   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2528                            arith_extended_reg32to64_i64, mnemonic, OpNode> {
2529     let Inst{31} = 1;
2530   }
2531   }
2533   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2534                                arith_extendlsl64, mnemonic> {
2535     // UXTX and SXTX only.
2536     let Inst{14-13} = 0b11;
2537     let Inst{31} = 1;
2538   }
2540   // add Rd, Rb, -imm -> sub Rd, Rn, imm
2541   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2542                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2543                       addsub_shifted_imm32_neg:$imm), 0>;
2544   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2545                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2546                        addsub_shifted_imm64_neg:$imm), 0>;
2548   // Register/register aliases with no shift when SP is not used.
2549   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2550                        GPR32, GPR32, GPR32, 0>;
2551   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2552                        GPR64, GPR64, GPR64, 0>;
2554   // Register/register aliases with no shift when either the destination or
2555   // first source register is SP.
2556   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2557                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2558   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2559                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2560   def : AddSubRegAlias<mnemonic,
2561                        !cast<Instruction>(NAME#"Xrx64"),
2562                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2563   def : AddSubRegAlias<mnemonic,
2564                        !cast<Instruction>(NAME#"Xrx64"),
2565                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2568 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2569                    string alias, string cmpAlias> {
2570   let isCompare = 1, Defs = [NZCV] in {
2571   // Add/Subtract immediate
2572   def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2573                            mnemonic, OpNode> {
2574     let Inst{31} = 0;
2575   }
2576   def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2577                            mnemonic, OpNode> {
2578     let Inst{31} = 1;
2579   }
2581   // Add/Subtract register
2582   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2583   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2585   // Add/Subtract shifted register
2586   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2587                            OpNode> {
2588     let Inst{31} = 0;
2589   }
2590   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2591                            OpNode> {
2592     let Inst{31} = 1;
2593   }
2595   // Add/Subtract extended register
2596   let AddedComplexity = 1 in {
2597   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2598                            arith_extended_reg32_i32, mnemonic, OpNode> {
2599     let Inst{31} = 0;
2600   }
2601   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2602                            arith_extended_reg32_i64, mnemonic, OpNode> {
2603     let Inst{31} = 1;
2604   }
2605   }
2607   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2608                                arith_extendlsl64, mnemonic> {
2609     // UXTX and SXTX only.
2610     let Inst{14-13} = 0b11;
2611     let Inst{31} = 1;
2612   }
2613   } // Defs = [NZCV]
2615   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2616   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2617                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2618                       addsub_shifted_imm32_neg:$imm), 0>;
2619   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2620                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2621                        addsub_shifted_imm64_neg:$imm), 0>;
2623   // Compare aliases
2624   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2625                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2626   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2627                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2628   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2629                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2630   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2631                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2632   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2633                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2634   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2635                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2636   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2637                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2639   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2640   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2641                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2642   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2643                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2645   // Compare shorthands
2646   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2647                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2648   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2649                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2650   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2651                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2652   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2653                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2655   // Register/register aliases with no shift when SP is not used.
2656   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2657                        GPR32, GPR32, GPR32, 0>;
2658   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2659                        GPR64, GPR64, GPR64, 0>;
2661   // Register/register aliases with no shift when the first source register
2662   // is SP.
2663   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2664                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2665   def : AddSubRegAlias<mnemonic,
2666                        !cast<Instruction>(NAME#"Xrx64"),
2667                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2670 class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2671       : BaseAddSubImm<
2672           isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2673           (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2674           (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2675   bits<6> imm6;
2676   bits<4> imm4;
2677   let Inst{31} = 1;
2678   let Inst{23-22} = 0b10;
2679   let Inst{21-16} = imm6;
2680   let Inst{15-14} = 0b00;
2681   let Inst{13-10} = imm4;
2682   let Unpredictable{15-14} = 0b11;
2685 class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2686       : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2687   let Inst{31} = 1;
2688   let Inst{29} = setsFlags;
2691 //---
2692 // Extract
2693 //---
2694 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2695                                       SDTCisPtrTy<3>]>;
2696 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2698 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2699                      list<dag> patterns>
2700     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2701          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2702       Sched<[WriteExtr, ReadExtrHi]> {
2703   bits<5> Rd;
2704   bits<5> Rn;
2705   bits<5> Rm;
2706   bits<6> imm;
2708   let Inst{30-23} = 0b00100111;
2709   let Inst{21}    = 0;
2710   let Inst{20-16} = Rm;
2711   let Inst{15-10} = imm;
2712   let Inst{9-5}   = Rn;
2713   let Inst{4-0}   = Rd;
2716 multiclass ExtractImm<string asm> {
2717   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2718                       [(set GPR32:$Rd,
2719                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2720     let Inst{31} = 0;
2721     let Inst{22} = 0;
2722     // imm<5> must be zero.
2723     let imm{5}   = 0;
2724   }
2725   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2726                       [(set GPR64:$Rd,
2727                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2729     let Inst{31} = 1;
2730     let Inst{22} = 1;
2731   }
2734 //---
2735 // Bitfield
2736 //---
2738 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2739 class BaseBitfieldImm<bits<2> opc,
2740                       RegisterClass regtype, Operand imm_type, string asm>
2741     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2742          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2743       Sched<[WriteIS, ReadI]> {
2744   bits<5> Rd;
2745   bits<5> Rn;
2746   bits<6> immr;
2747   bits<6> imms;
2749   let Inst{30-29} = opc;
2750   let Inst{28-23} = 0b100110;
2751   let Inst{21-16} = immr;
2752   let Inst{15-10} = imms;
2753   let Inst{9-5}   = Rn;
2754   let Inst{4-0}   = Rd;
2757 multiclass BitfieldImm<bits<2> opc, string asm> {
2758   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2759     let Inst{31} = 0;
2760     let Inst{22} = 0;
2761     // imms<5> and immr<5> must be zero, else ReservedValue().
2762     let Inst{21} = 0;
2763     let Inst{15} = 0;
2764   }
2765   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2766     let Inst{31} = 1;
2767     let Inst{22} = 1;
2768   }
2771 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2772 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2773                       RegisterClass regtype, Operand imm_type, string asm>
2774     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2775                              imm_type:$imms),
2776          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2777       Sched<[WriteIS, ReadI]> {
2778   bits<5> Rd;
2779   bits<5> Rn;
2780   bits<6> immr;
2781   bits<6> imms;
2783   let Inst{30-29} = opc;
2784   let Inst{28-23} = 0b100110;
2785   let Inst{21-16} = immr;
2786   let Inst{15-10} = imms;
2787   let Inst{9-5}   = Rn;
2788   let Inst{4-0}   = Rd;
2791 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2792   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2793     let Inst{31} = 0;
2794     let Inst{22} = 0;
2795     // imms<5> and immr<5> must be zero, else ReservedValue().
2796     let Inst{21} = 0;
2797     let Inst{15} = 0;
2798   }
2799   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2800     let Inst{31} = 1;
2801     let Inst{22} = 1;
2802   }
2805 //---
2806 // Logical
2807 //---
2809 // Logical (immediate)
2810 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2811                      RegisterClass sregtype, Operand imm_type, string asm,
2812                      list<dag> pattern>
2813     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2814          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2815       Sched<[WriteI, ReadI]> {
2816   bits<5>  Rd;
2817   bits<5>  Rn;
2818   bits<13> imm;
2819   let Inst{30-29} = opc;
2820   let Inst{28-23} = 0b100100;
2821   let Inst{22}    = imm{12};
2822   let Inst{21-16} = imm{11-6};
2823   let Inst{15-10} = imm{5-0};
2824   let Inst{9-5}   = Rn;
2825   let Inst{4-0}   = Rd;
2827   let DecoderMethod = "DecodeLogicalImmInstruction";
2830 // Logical (shifted register)
2831 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2832                       logical_shifted_reg shifted_regtype, string asm,
2833                       list<dag> pattern>
2834     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2835         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2836       Sched<[WriteISReg, ReadI, ReadISReg]> {
2837   // The operands are in order to match the 'addr' MI operands, so we
2838   // don't need an encoder method and by-name matching. Just use the default
2839   // in-order handling. Since we're using by-order, make sure the names
2840   // do not match.
2841   bits<5> dst;
2842   bits<5> src1;
2843   bits<5> src2;
2844   bits<8> shift;
2845   let Inst{30-29} = opc;
2846   let Inst{28-24} = 0b01010;
2847   let Inst{23-22} = shift{7-6};
2848   let Inst{21}    = N;
2849   let Inst{20-16} = src2;
2850   let Inst{15-10} = shift{5-0};
2851   let Inst{9-5}   = src1;
2852   let Inst{4-0}   = dst;
2854   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2857 // Aliases for register+register logical instructions.
2858 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2859     : InstAlias<asm#"\t$dst, $src1, $src2",
2860                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2862 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2863                       string Alias> {
2864   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2865   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2866                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2867                                                logical_imm32:$imm))]> {
2868     let Inst{31} = 0;
2869     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2870   }
2871   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2872   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2873                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2874                                                logical_imm64:$imm))]> {
2875     let Inst{31} = 1;
2876   }
2878   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2879                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2880                       logical_imm32_not:$imm), 0>;
2881   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2882                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2883                        logical_imm64_not:$imm), 0>;
2886 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2887                        string Alias> {
2888   let isCompare = 1, Defs = [NZCV] in {
2889   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2890       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2891     let Inst{31} = 0;
2892     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2893   }
2894   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2895       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2896     let Inst{31} = 1;
2897   }
2898   } // end Defs = [NZCV]
2900   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2901                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2902                       logical_imm32_not:$imm), 0>;
2903   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2904                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2905                        logical_imm64_not:$imm), 0>;
2908 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2909     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2910              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2911       Sched<[WriteI, ReadI, ReadI]>;
2913 // Split from LogicalImm as not all instructions have both.
2914 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2915                       SDPatternOperator OpNode> {
2916   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2917   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2918   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2919   }
2921   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2922                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2923                                                  logical_shifted_reg32:$Rm))]> {
2924     let Inst{31} = 0;
2925   }
2926   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2927                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2928                                                  logical_shifted_reg64:$Rm))]> {
2929     let Inst{31} = 1;
2930   }
2932   def : LogicalRegAlias<mnemonic,
2933                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2934   def : LogicalRegAlias<mnemonic,
2935                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2938 // Split from LogicalReg to allow setting NZCV Defs
2939 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2940                        SDPatternOperator OpNode = null_frag> {
2941   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2942   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2943   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2945   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2946             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2947     let Inst{31} = 0;
2948   }
2949   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2950             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2951     let Inst{31} = 1;
2952   }
2953   } // Defs = [NZCV]
2955   def : LogicalRegAlias<mnemonic,
2956                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2957   def : LogicalRegAlias<mnemonic,
2958                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2961 //---
2962 // Conditionally set flags
2963 //---
2965 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2966 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2967                             string mnemonic, SDNode OpNode>
2968     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2969          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2970          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2971                              (i32 imm:$cond), NZCV))]>,
2972       Sched<[WriteI, ReadI]> {
2973   let Uses = [NZCV];
2974   let Defs = [NZCV];
2976   bits<5> Rn;
2977   bits<5> imm;
2978   bits<4> nzcv;
2979   bits<4> cond;
2981   let Inst{30}    = op;
2982   let Inst{29-21} = 0b111010010;
2983   let Inst{20-16} = imm;
2984   let Inst{15-12} = cond;
2985   let Inst{11-10} = 0b10;
2986   let Inst{9-5}   = Rn;
2987   let Inst{4}     = 0b0;
2988   let Inst{3-0}   = nzcv;
2991 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2992 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2993                             SDNode OpNode>
2994     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2995          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2996          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2997                              (i32 imm:$cond), NZCV))]>,
2998       Sched<[WriteI, ReadI, ReadI]> {
2999   let Uses = [NZCV];
3000   let Defs = [NZCV];
3002   bits<5> Rn;
3003   bits<5> Rm;
3004   bits<4> nzcv;
3005   bits<4> cond;
3007   let Inst{30}    = op;
3008   let Inst{29-21} = 0b111010010;
3009   let Inst{20-16} = Rm;
3010   let Inst{15-12} = cond;
3011   let Inst{11-10} = 0b00;
3012   let Inst{9-5}   = Rn;
3013   let Inst{4}     = 0b0;
3014   let Inst{3-0}   = nzcv;
3017 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3018   // immediate operand variants
3019   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3020     let Inst{31} = 0;
3021   }
3022   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3023     let Inst{31} = 1;
3024   }
3025   // register operand variants
3026   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3027     let Inst{31} = 0;
3028   }
3029   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3030     let Inst{31} = 1;
3031   }
3034 //---
3035 // Conditional select
3036 //---
3038 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3039     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3040          asm, "\t$Rd, $Rn, $Rm, $cond", "",
3041          [(set regtype:$Rd,
3042                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3043       Sched<[WriteI, ReadI, ReadI]> {
3044   let Uses = [NZCV];
3046   bits<5> Rd;
3047   bits<5> Rn;
3048   bits<5> Rm;
3049   bits<4> cond;
3051   let Inst{30}    = op;
3052   let Inst{29-21} = 0b011010100;
3053   let Inst{20-16} = Rm;
3054   let Inst{15-12} = cond;
3055   let Inst{11-10} = op2;
3056   let Inst{9-5}   = Rn;
3057   let Inst{4-0}   = Rd;
3060 multiclass CondSelect<bit op, bits<2> op2, string asm> {
3061   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3062     let Inst{31} = 0;
3063   }
3064   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3065     let Inst{31} = 1;
3066   }
3069 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3070                        PatFrag frag>
3071     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3072          asm, "\t$Rd, $Rn, $Rm, $cond", "",
3073          [(set regtype:$Rd,
3074                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3075                (i32 imm:$cond), NZCV))]>,
3076       Sched<[WriteI, ReadI, ReadI]> {
3077   let Uses = [NZCV];
3079   bits<5> Rd;
3080   bits<5> Rn;
3081   bits<5> Rm;
3082   bits<4> cond;
3084   let Inst{30}    = op;
3085   let Inst{29-21} = 0b011010100;
3086   let Inst{20-16} = Rm;
3087   let Inst{15-12} = cond;
3088   let Inst{11-10} = op2;
3089   let Inst{9-5}   = Rn;
3090   let Inst{4-0}   = Rd;
3093 def inv_cond_XFORM : SDNodeXForm<imm, [{
3094   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3095   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3096                                    MVT::i32);
3097 }]>;
3099 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3100   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3101     let Inst{31} = 0;
3102   }
3103   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3104     let Inst{31} = 1;
3105   }
3107   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3108             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3109                                            (inv_cond_XFORM imm:$cond))>;
3111   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3112             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3113                                            (inv_cond_XFORM imm:$cond))>;
3116 //---
3117 // Special Mask Value
3118 //---
3119 def maski8_or_more : Operand<i32>,
3120   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3122 def maski16_or_more : Operand<i32>,
3123   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3127 //---
3128 // Load/store
3129 //---
3131 // (unsigned immediate)
3132 // Indexed for 8-bit registers. offset is in range [0,4095].
3133 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
3134 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
3135 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
3136 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
3137 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
3139 // (unsigned immediate)
3140 // Indexed for 8-bit registers. offset is in range [0,63].
3141 def am_indexed8_6b : ComplexPattern<i64, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3142 def am_indexed16_6b : ComplexPattern<i64, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3143 def am_indexed32_6b : ComplexPattern<i64, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3144 def am_indexed64_6b : ComplexPattern<i64, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3146 def gi_am_indexed8 :
3147     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3148     GIComplexPatternEquiv<am_indexed8>;
3149 def gi_am_indexed16 :
3150     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3151     GIComplexPatternEquiv<am_indexed16>;
3152 def gi_am_indexed32 :
3153     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3154     GIComplexPatternEquiv<am_indexed32>;
3155 def gi_am_indexed64 :
3156     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3157     GIComplexPatternEquiv<am_indexed64>;
3158 def gi_am_indexed128 :
3159     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3160     GIComplexPatternEquiv<am_indexed128>;
3162 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3163   let Name = "UImm12Offset" # Scale;
3164   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3165   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3166   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3169 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3170 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3171 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3172 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3173 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3175 class uimm12_scaled<int Scale> : Operand<i64> {
3176   let ParserMatchClass
3177    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3178   let EncoderMethod
3179    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3180   let PrintMethod = "printUImm12Offset<" # Scale # ">";
3183 def uimm12s1 : uimm12_scaled<1>;
3184 def uimm12s2 : uimm12_scaled<2>;
3185 def uimm12s4 : uimm12_scaled<4>;
3186 def uimm12s8 : uimm12_scaled<8>;
3187 def uimm12s16 : uimm12_scaled<16>;
3189 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3190                       string asm, list<dag> pattern>
3191     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3192   bits<5> Rt;
3194   bits<5> Rn;
3195   bits<12> offset;
3197   let Inst{31-30} = sz;
3198   let Inst{29-27} = 0b111;
3199   let Inst{26}    = V;
3200   let Inst{25-24} = 0b01;
3201   let Inst{23-22} = opc;
3202   let Inst{21-10} = offset;
3203   let Inst{9-5}   = Rn;
3204   let Inst{4-0}   = Rt;
3206   let DecoderMethod = "DecodeUnsignedLdStInstruction";
3209 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3210                   Operand indextype, string asm, list<dag> pattern> {
3211   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3212   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3213                            (ins GPR64sp:$Rn, indextype:$offset),
3214                            asm, pattern>,
3215            Sched<[WriteLD]>;
3217   def : InstAlias<asm # "\t$Rt, [$Rn]",
3218                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3221 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3222              Operand indextype, string asm, list<dag> pattern> {
3223   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3224   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3225                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3226                            asm, pattern>,
3227            Sched<[WriteST]>;
3229   def : InstAlias<asm # "\t$Rt, [$Rn]",
3230                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3233 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3234 // substitute zero-registers automatically.
3236 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3237 //       into StoreUI.
3238 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3239              Operand indextype, string asm, list<dag> pattern> {
3240   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3241   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3242                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3243                            asm, pattern>,
3244            Sched<[WriteST]>;
3246   def : InstAlias<asm # "\t$Rt, [$Rn]",
3247                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3250 def PrefetchOperand : AsmOperandClass {
3251   let Name = "Prefetch";
3252   let ParserMethod = "tryParsePrefetch";
3254 def prfop : Operand<i32> {
3255   let PrintMethod = "printPrefetchOp";
3256   let ParserMatchClass = PrefetchOperand;
3259 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3260 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3261     : BaseLoadStoreUI<sz, V, opc,
3262                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3263                       asm, pat>,
3264       Sched<[WriteLD]>;
3266 //---
3267 // Load literal
3268 //---
3270 // Load literal address: 19-bit immediate. The low two bits of the target
3271 // offset are implied zero and so are not part of the immediate.
3272 def am_ldrlit : Operand<iPTR> {
3273   let EncoderMethod = "getLoadLiteralOpValue";
3274   let DecoderMethod = "DecodePCRelLabel19";
3275   let PrintMethod = "printAlignedLabel";
3276   let ParserMatchClass = PCRelLabel19Operand;
3277   let OperandType = "OPERAND_PCREL";
3280 let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3281 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3282     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3283         asm, "\t$Rt, $label", "", pat>,
3284       Sched<[WriteLD]> {
3285   bits<5> Rt;
3286   bits<19> label;
3287   let Inst{31-30} = opc;
3288   let Inst{29-27} = 0b011;
3289   let Inst{26}    = V;
3290   let Inst{25-24} = 0b00;
3291   let Inst{23-5}  = label;
3292   let Inst{4-0}   = Rt;
3295 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3296 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3297     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3298         asm, "\t$Rt, $label", "", pat>,
3299       Sched<[WriteLD]> {
3300   bits<5> Rt;
3301   bits<19> label;
3302   let Inst{31-30} = opc;
3303   let Inst{29-27} = 0b011;
3304   let Inst{26}    = V;
3305   let Inst{25-24} = 0b00;
3306   let Inst{23-5}  = label;
3307   let Inst{4-0}   = Rt;
3310 //---
3311 // Load/store register offset
3312 //---
3314 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3315 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3316 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3317 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3318 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3320 def gi_ro_Xindexed8 :
3321     GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3322     GIComplexPatternEquiv<ro_Xindexed8>;
3323 def gi_ro_Xindexed16 :
3324     GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3325     GIComplexPatternEquiv<ro_Xindexed16>;
3326 def gi_ro_Xindexed32 :
3327     GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3328     GIComplexPatternEquiv<ro_Xindexed32>;
3329 def gi_ro_Xindexed64 :
3330     GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3331     GIComplexPatternEquiv<ro_Xindexed64>;
3332 def gi_ro_Xindexed128 :
3333     GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3334     GIComplexPatternEquiv<ro_Xindexed128>;
3336 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3337 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3338 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3339 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3340 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3342 def gi_ro_Windexed8 :
3343     GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3344     GIComplexPatternEquiv<ro_Windexed8>;
3345 def gi_ro_Windexed16 :
3346     GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3347     GIComplexPatternEquiv<ro_Windexed16>;
3348 def gi_ro_Windexed32 :
3349     GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3350     GIComplexPatternEquiv<ro_Windexed32>;
3351 def gi_ro_Windexed64 :
3352     GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3353     GIComplexPatternEquiv<ro_Windexed64>;
3354 def gi_ro_Windexed128 :
3355     GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3356     GIComplexPatternEquiv<ro_Windexed128>;
3358 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3359   let Name = "Mem" # Reg # "Extend" # Width;
3360   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3361   let RenderMethod = "addMemExtendOperands";
3362   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3365 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3366   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3367   // the trivial shift.
3368   let RenderMethod = "addMemExtend8Operands";
3370 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3371 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3372 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3373 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3375 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3376   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3377   // the trivial shift.
3378   let RenderMethod = "addMemExtend8Operands";
3380 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3381 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3382 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3383 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3385 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3386         : Operand<i32> {
3387   let ParserMatchClass = ParserClass;
3388   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3389   let DecoderMethod = "DecodeMemExtend";
3390   let EncoderMethod = "getMemExtendOpValue";
3391   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3394 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3395 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3396 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3397 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3398 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3400 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3401 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3402 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3403 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3404 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3406 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3407                   Operand wextend, Operand xextend>  {
3408   // CodeGen-level pattern covering the entire addressing mode.
3409   ComplexPattern Wpat = windex;
3410   ComplexPattern Xpat = xindex;
3412   // Asm-level Operand covering the valid "uxtw #3" style syntax.
3413   Operand Wext = wextend;
3414   Operand Xext = xextend;
3417 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3418 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3419 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3420 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3421 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3422                        ro_Xextend128>;
3424 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3425                       string asm, dag ins, dag outs, list<dag> pat>
3426     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3427   bits<5> Rt;
3428   bits<5> Rn;
3429   bits<5> Rm;
3430   bits<2> extend;
3431   let Inst{31-30} = sz;
3432   let Inst{29-27} = 0b111;
3433   let Inst{26}    = V;
3434   let Inst{25-24} = 0b00;
3435   let Inst{23-22} = opc;
3436   let Inst{21}    = 1;
3437   let Inst{20-16} = Rm;
3438   let Inst{15}    = extend{1}; // sign extend Rm?
3439   let Inst{14}    = 1;
3440   let Inst{12}    = extend{0}; // do shift?
3441   let Inst{11-10} = 0b10;
3442   let Inst{9-5}   = Rn;
3443   let Inst{4-0}   = Rt;
3446 class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3447   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3448               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3450 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3451                    string asm, ValueType Ty, SDPatternOperator loadop> {
3452   let AddedComplexity = 10 in
3453   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3454                  (outs regtype:$Rt),
3455                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3456                  [(set (Ty regtype:$Rt),
3457                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3458                                              ro_Wextend8:$extend)))]>,
3459            Sched<[WriteLDIdx, ReadAdrBase]> {
3460     let Inst{13} = 0b0;
3461   }
3463   let AddedComplexity = 10 in
3464   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3465                  (outs regtype:$Rt),
3466                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3467                  [(set (Ty regtype:$Rt),
3468                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3469                                              ro_Xextend8:$extend)))]>,
3470            Sched<[WriteLDIdx, ReadAdrBase]> {
3471     let Inst{13} = 0b1;
3472   }
3474   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3477 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3478                     string asm, ValueType Ty, SDPatternOperator storeop> {
3479   let AddedComplexity = 10 in
3480   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3481                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3482                  [(storeop (Ty regtype:$Rt),
3483                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3484                                          ro_Wextend8:$extend))]>,
3485             Sched<[WriteSTIdx, ReadAdrBase]> {
3486     let Inst{13} = 0b0;
3487   }
3489   let AddedComplexity = 10 in
3490   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3491                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3492                  [(storeop (Ty regtype:$Rt),
3493                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3494                                          ro_Xextend8:$extend))]>,
3495             Sched<[WriteSTIdx, ReadAdrBase]> {
3496     let Inst{13} = 0b1;
3497   }
3499   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3502 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3503                       string asm, dag ins, dag outs, list<dag> pat>
3504     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3505   bits<5> Rt;
3506   bits<5> Rn;
3507   bits<5> Rm;
3508   bits<2> extend;
3509   let Inst{31-30} = sz;
3510   let Inst{29-27} = 0b111;
3511   let Inst{26}    = V;
3512   let Inst{25-24} = 0b00;
3513   let Inst{23-22} = opc;
3514   let Inst{21}    = 1;
3515   let Inst{20-16} = Rm;
3516   let Inst{15}    = extend{1}; // sign extend Rm?
3517   let Inst{14}    = 1;
3518   let Inst{12}    = extend{0}; // do shift?
3519   let Inst{11-10} = 0b10;
3520   let Inst{9-5}   = Rn;
3521   let Inst{4-0}   = Rt;
3524 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3525                     string asm, ValueType Ty, SDPatternOperator loadop> {
3526   let AddedComplexity = 10 in
3527   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3528                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3529                  [(set (Ty regtype:$Rt),
3530                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3531                                               ro_Wextend16:$extend)))]>,
3532             Sched<[WriteLDIdx, ReadAdrBase]> {
3533     let Inst{13} = 0b0;
3534   }
3536   let AddedComplexity = 10 in
3537   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3538                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3539                  [(set (Ty regtype:$Rt),
3540                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3541                                              ro_Xextend16:$extend)))]>,
3542             Sched<[WriteLDIdx, ReadAdrBase]> {
3543     let Inst{13} = 0b1;
3544   }
3546   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3549 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3550                      string asm, ValueType Ty, SDPatternOperator storeop> {
3551   let AddedComplexity = 10 in
3552   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3553                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3554                 [(storeop (Ty regtype:$Rt),
3555                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3556                                          ro_Wextend16:$extend))]>,
3557            Sched<[WriteSTIdx, ReadAdrBase]> {
3558     let Inst{13} = 0b0;
3559   }
3561   let AddedComplexity = 10 in
3562   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3563                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3564                 [(storeop (Ty regtype:$Rt),
3565                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3566                                          ro_Xextend16:$extend))]>,
3567            Sched<[WriteSTIdx, ReadAdrBase]> {
3568     let Inst{13} = 0b1;
3569   }
3571   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3574 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3575                       string asm, dag ins, dag outs, list<dag> pat>
3576     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3577   bits<5> Rt;
3578   bits<5> Rn;
3579   bits<5> Rm;
3580   bits<2> extend;
3581   let Inst{31-30} = sz;
3582   let Inst{29-27} = 0b111;
3583   let Inst{26}    = V;
3584   let Inst{25-24} = 0b00;
3585   let Inst{23-22} = opc;
3586   let Inst{21}    = 1;
3587   let Inst{20-16} = Rm;
3588   let Inst{15}    = extend{1}; // sign extend Rm?
3589   let Inst{14}    = 1;
3590   let Inst{12}    = extend{0}; // do shift?
3591   let Inst{11-10} = 0b10;
3592   let Inst{9-5}   = Rn;
3593   let Inst{4-0}   = Rt;
3596 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3597                     string asm, ValueType Ty, SDPatternOperator loadop> {
3598   let AddedComplexity = 10 in
3599   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3600                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3601                  [(set (Ty regtype:$Rt),
3602                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3603                                               ro_Wextend32:$extend)))]>,
3604            Sched<[WriteLDIdx, ReadAdrBase]> {
3605     let Inst{13} = 0b0;
3606   }
3608   let AddedComplexity = 10 in
3609   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3610                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3611                  [(set (Ty regtype:$Rt),
3612                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3613                                               ro_Xextend32:$extend)))]>,
3614            Sched<[WriteLDIdx, ReadAdrBase]> {
3615     let Inst{13} = 0b1;
3616   }
3618   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3621 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3622                      string asm, ValueType Ty, SDPatternOperator storeop> {
3623   let AddedComplexity = 10 in
3624   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3625                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3626                 [(storeop (Ty regtype:$Rt),
3627                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3628                                          ro_Wextend32:$extend))]>,
3629             Sched<[WriteSTIdx, ReadAdrBase]> {
3630     let Inst{13} = 0b0;
3631   }
3633   let AddedComplexity = 10 in
3634   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3635                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3636                 [(storeop (Ty regtype:$Rt),
3637                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3638                                         ro_Xextend32:$extend))]>,
3639             Sched<[WriteSTIdx, ReadAdrBase]> {
3640     let Inst{13} = 0b1;
3641   }
3643   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3646 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3647                       string asm, dag ins, dag outs, list<dag> pat>
3648     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3649   bits<5> Rt;
3650   bits<5> Rn;
3651   bits<5> Rm;
3652   bits<2> extend;
3653   let Inst{31-30} = sz;
3654   let Inst{29-27} = 0b111;
3655   let Inst{26}    = V;
3656   let Inst{25-24} = 0b00;
3657   let Inst{23-22} = opc;
3658   let Inst{21}    = 1;
3659   let Inst{20-16} = Rm;
3660   let Inst{15}    = extend{1}; // sign extend Rm?
3661   let Inst{14}    = 1;
3662   let Inst{12}    = extend{0}; // do shift?
3663   let Inst{11-10} = 0b10;
3664   let Inst{9-5}   = Rn;
3665   let Inst{4-0}   = Rt;
3668 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3669                     string asm, ValueType Ty, SDPatternOperator loadop> {
3670   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3671   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3672                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3673                 [(set (Ty regtype:$Rt),
3674                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3675                                              ro_Wextend64:$extend)))]>,
3676            Sched<[WriteLDIdx, ReadAdrBase]> {
3677     let Inst{13} = 0b0;
3678   }
3680   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3681   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3682                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3683                  [(set (Ty regtype:$Rt),
3684                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3685                                               ro_Xextend64:$extend)))]>,
3686            Sched<[WriteLDIdx, ReadAdrBase]> {
3687     let Inst{13} = 0b1;
3688   }
3690   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3693 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3694                      string asm, ValueType Ty, SDPatternOperator storeop> {
3695   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3696   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3697                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3698                 [(storeop (Ty regtype:$Rt),
3699                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3700                                          ro_Wextend64:$extend))]>,
3701             Sched<[WriteSTIdx, ReadAdrBase]> {
3702     let Inst{13} = 0b0;
3703   }
3705   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3706   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3707                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3708                 [(storeop (Ty regtype:$Rt),
3709                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3710                                          ro_Xextend64:$extend))]>,
3711             Sched<[WriteSTIdx, ReadAdrBase]> {
3712     let Inst{13} = 0b1;
3713   }
3715   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3718 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3719                       string asm, dag ins, dag outs, list<dag> pat>
3720     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3721   bits<5> Rt;
3722   bits<5> Rn;
3723   bits<5> Rm;
3724   bits<2> extend;
3725   let Inst{31-30} = sz;
3726   let Inst{29-27} = 0b111;
3727   let Inst{26}    = V;
3728   let Inst{25-24} = 0b00;
3729   let Inst{23-22} = opc;
3730   let Inst{21}    = 1;
3731   let Inst{20-16} = Rm;
3732   let Inst{15}    = extend{1}; // sign extend Rm?
3733   let Inst{14}    = 1;
3734   let Inst{12}    = extend{0}; // do shift?
3735   let Inst{11-10} = 0b10;
3736   let Inst{9-5}   = Rn;
3737   let Inst{4-0}   = Rt;
3740 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3741                      string asm, ValueType Ty, SDPatternOperator loadop> {
3742   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3743   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3744                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3745                  [(set (Ty regtype:$Rt),
3746                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3747                                                ro_Wextend128:$extend)))]>,
3748             Sched<[WriteLDIdx, ReadAdrBase]> {
3749     let Inst{13} = 0b0;
3750   }
3752   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3753   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3754                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3755                  [(set (Ty regtype:$Rt),
3756                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3757                                                ro_Xextend128:$extend)))]>,
3758             Sched<[WriteLDIdx, ReadAdrBase]> {
3759     let Inst{13} = 0b1;
3760   }
3762   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3765 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3766                       string asm, ValueType Ty, SDPatternOperator storeop> {
3767   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3768   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3769                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3770                 []>,
3771             Sched<[WriteSTIdx, ReadAdrBase]> {
3772     let Inst{13} = 0b0;
3773   }
3775   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3776   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3777                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3778                 []>,
3779             Sched<[WriteSTIdx, ReadAdrBase]> {
3780     let Inst{13} = 0b1;
3781   }
3783   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3786 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3787 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3788                      string asm, list<dag> pat>
3789     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3790       Sched<[WriteLD]> {
3791   bits<5> Rt;
3792   bits<5> Rn;
3793   bits<5> Rm;
3794   bits<2> extend;
3795   let Inst{31-30} = sz;
3796   let Inst{29-27} = 0b111;
3797   let Inst{26}    = V;
3798   let Inst{25-24} = 0b00;
3799   let Inst{23-22} = opc;
3800   let Inst{21}    = 1;
3801   let Inst{20-16} = Rm;
3802   let Inst{15}    = extend{1}; // sign extend Rm?
3803   let Inst{14}    = 1;
3804   let Inst{12}    = extend{0}; // do shift?
3805   let Inst{11-10} = 0b10;
3806   let Inst{9-5}   = Rn;
3807   let Inst{4-0}   = Rt;
3810 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3811   def roW : BasePrefetchRO<sz, V, opc, (outs),
3812                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3813                 asm, [(AArch64Prefetch imm:$Rt,
3814                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3815                                                     ro_Wextend64:$extend))]> {
3816     let Inst{13} = 0b0;
3817   }
3819   def roX : BasePrefetchRO<sz, V, opc, (outs),
3820                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3821                 asm,  [(AArch64Prefetch imm:$Rt,
3822                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3823                                                      ro_Xextend64:$extend))]> {
3824     let Inst{13} = 0b1;
3825   }
3827   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3828                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3829                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3832 //---
3833 // Load/store unscaled immediate
3834 //---
3836 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3837 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3838 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3839 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3840 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3842 def gi_am_unscaled8 :
3843     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3844     GIComplexPatternEquiv<am_unscaled8>;
3845 def gi_am_unscaled16 :
3846     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3847     GIComplexPatternEquiv<am_unscaled16>;
3848 def gi_am_unscaled32 :
3849     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3850     GIComplexPatternEquiv<am_unscaled32>;
3851 def gi_am_unscaled64 :
3852     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3853     GIComplexPatternEquiv<am_unscaled64>;
3854 def gi_am_unscaled128 :
3855     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3856     GIComplexPatternEquiv<am_unscaled128>;
3859 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3860                            string asm, list<dag> pattern>
3861     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3862   bits<5> Rt;
3863   bits<5> Rn;
3864   bits<9> offset;
3865   let Inst{31-30} = sz;
3866   let Inst{29-27} = 0b111;
3867   let Inst{26}    = V;
3868   let Inst{25-24} = 0b00;
3869   let Inst{23-22} = opc;
3870   let Inst{21}    = 0;
3871   let Inst{20-12} = offset;
3872   let Inst{11-10} = 0b00;
3873   let Inst{9-5}   = Rn;
3874   let Inst{4-0}   = Rt;
3876   let DecoderMethod = "DecodeSignedLdStInstruction";
3879 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3880 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3881                               DAGOperand regtype > {
3882   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3883                                (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3884           Sched<[WriteST]> {
3885     let Inst{29} = 0;
3886     let Inst{24} = 1;
3887   }
3888   def : InstAlias<asm # "\t$Rt, [$Rn]",
3889                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3892 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3893                                DAGOperand regtype > {
3894   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3895                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3896                                asm, []>,
3897           Sched<[WriteST]> {
3898     let Inst{29} = 0;
3899     let Inst{24} = 1;
3900   }
3901   def : InstAlias<asm # "\t$Rt, [$Rn]",
3902                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3905 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3906                    string asm, list<dag> pattern> {
3907   let AddedComplexity = 1 in // try this before LoadUI
3908   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3909                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3910           Sched<[WriteLD]>;
3912   def : InstAlias<asm # "\t$Rt, [$Rn]",
3913                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3916 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3917                          string asm, list<dag> pattern> {
3918   let AddedComplexity = 1 in // try this before StoreUI
3919   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3920                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3921                                asm, pattern>,
3922           Sched<[WriteST]>;
3924   def : InstAlias<asm # "\t$Rt, [$Rn]",
3925                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3928 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3929                             list<dag> pat> {
3930   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3931   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3932                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3933                                asm, pat>,
3934           Sched<[WriteLD]>;
3936   def : InstAlias<asm # "\t$Rt, [$Rn]",
3937                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3940 //---
3941 // Load/store unscaled immediate, unprivileged
3942 //---
3944 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3945                                 dag oops, dag iops, string asm>
3946     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3947   bits<5> Rt;
3948   bits<5> Rn;
3949   bits<9> offset;
3950   let Inst{31-30} = sz;
3951   let Inst{29-27} = 0b111;
3952   let Inst{26}    = V;
3953   let Inst{25-24} = 0b00;
3954   let Inst{23-22} = opc;
3955   let Inst{21}    = 0;
3956   let Inst{20-12} = offset;
3957   let Inst{11-10} = 0b10;
3958   let Inst{9-5}   = Rn;
3959   let Inst{4-0}   = Rt;
3961   let DecoderMethod = "DecodeSignedLdStInstruction";
3964 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3965                             RegisterClass regtype, string asm> {
3966   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3967   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3968                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3969           Sched<[WriteLD]>;
3971   def : InstAlias<asm # "\t$Rt, [$Rn]",
3972                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3975 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3976                              RegisterClass regtype, string asm> {
3977   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3978   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3979                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3980                                  asm>,
3981           Sched<[WriteST]>;
3983   def : InstAlias<asm # "\t$Rt, [$Rn]",
3984                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3987 //---
3988 // Load/store pre-indexed
3989 //---
3991 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3992                           string asm, string cstr, list<dag> pat>
3993     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3994   bits<5> Rt;
3995   bits<5> Rn;
3996   bits<9> offset;
3997   let Inst{31-30} = sz;
3998   let Inst{29-27} = 0b111;
3999   let Inst{26}    = V;
4000   let Inst{25-24} = 0;
4001   let Inst{23-22} = opc;
4002   let Inst{21}    = 0;
4003   let Inst{20-12} = offset;
4004   let Inst{11-10} = 0b11;
4005   let Inst{9-5}   = Rn;
4006   let Inst{4-0}   = Rt;
4008   let DecoderMethod = "DecodeSignedLdStInstruction";
4011 let hasSideEffects = 0 in {
4012 let mayStore = 0, mayLoad = 1 in
4013 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4014              string asm>
4015     : BaseLoadStorePreIdx<sz, V, opc,
4016                      (outs GPR64sp:$wback, regtype:$Rt),
4017                      (ins GPR64sp:$Rn, simm9:$offset), asm,
4018                      "$Rn = $wback,@earlyclobber $wback", []>,
4019       Sched<[WriteAdr, WriteLD]>;
4021 let mayStore = 1, mayLoad = 0 in
4022 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4023                   string asm, SDPatternOperator storeop, ValueType Ty>
4024     : BaseLoadStorePreIdx<sz, V, opc,
4025                       (outs GPR64sp:$wback),
4026                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4027                       asm, "$Rn = $wback,@earlyclobber $wback",
4028       [(set GPR64sp:$wback,
4029             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4030       Sched<[WriteAdr, WriteST]>;
4031 } // hasSideEffects = 0
4033 //---
4034 // Load/store post-indexed
4035 //---
4037 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4038                           string asm, string cstr, list<dag> pat>
4039     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4040   bits<5> Rt;
4041   bits<5> Rn;
4042   bits<9> offset;
4043   let Inst{31-30} = sz;
4044   let Inst{29-27} = 0b111;
4045   let Inst{26}    = V;
4046   let Inst{25-24} = 0b00;
4047   let Inst{23-22} = opc;
4048   let Inst{21}    = 0b0;
4049   let Inst{20-12} = offset;
4050   let Inst{11-10} = 0b01;
4051   let Inst{9-5}   = Rn;
4052   let Inst{4-0}   = Rt;
4054   let DecoderMethod = "DecodeSignedLdStInstruction";
4057 let hasSideEffects = 0 in {
4058 let mayStore = 0, mayLoad = 1 in
4059 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4060              string asm>
4061     : BaseLoadStorePostIdx<sz, V, opc,
4062                       (outs GPR64sp:$wback, regtype:$Rt),
4063                       (ins GPR64sp:$Rn, simm9:$offset),
4064                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
4065       Sched<[WriteAdr, WriteLD]>;
4067 let mayStore = 1, mayLoad = 0 in
4068 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4069                    string asm, SDPatternOperator storeop, ValueType Ty>
4070     : BaseLoadStorePostIdx<sz, V, opc,
4071                       (outs GPR64sp:$wback),
4072                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4073                        asm, "$Rn = $wback,@earlyclobber $wback",
4074       [(set GPR64sp:$wback,
4075             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4076     Sched<[WriteAdr, WriteST]>;
4077 } // hasSideEffects = 0
4080 //---
4081 // Load/store pair
4082 //---
4084 // (indexed, offset)
4086 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4087                               string asm>
4088     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4089   bits<5> Rt;
4090   bits<5> Rt2;
4091   bits<5> Rn;
4092   bits<7> offset;
4093   let Inst{31-30} = opc;
4094   let Inst{29-27} = 0b101;
4095   let Inst{26}    = V;
4096   let Inst{25-23} = 0b010;
4097   let Inst{22}    = L;
4098   let Inst{21-15} = offset;
4099   let Inst{14-10} = Rt2;
4100   let Inst{9-5}   = Rn;
4101   let Inst{4-0}   = Rt;
4103   let DecoderMethod = "DecodePairLdStInstruction";
4106 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4107                           Operand indextype, string asm> {
4108   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4109   def i : BaseLoadStorePairOffset<opc, V, 1,
4110                                   (outs regtype:$Rt, regtype:$Rt2),
4111                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4112           Sched<[WriteLD, WriteLDHi]>;
4114   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4115                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4116                                                   GPR64sp:$Rn, 0)>;
4120 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4121                            Operand indextype, string asm> {
4122   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4123   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4124                                   (ins regtype:$Rt, regtype:$Rt2,
4125                                        GPR64sp:$Rn, indextype:$offset),
4126                                   asm>,
4127           Sched<[WriteSTP]>;
4129   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4130                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4131                                                   GPR64sp:$Rn, 0)>;
4134 // (pre-indexed)
4135 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4136                               string asm>
4137     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4138   bits<5> Rt;
4139   bits<5> Rt2;
4140   bits<5> Rn;
4141   bits<7> offset;
4142   let Inst{31-30} = opc;
4143   let Inst{29-27} = 0b101;
4144   let Inst{26}    = V;
4145   let Inst{25-23} = 0b011;
4146   let Inst{22}    = L;
4147   let Inst{21-15} = offset;
4148   let Inst{14-10} = Rt2;
4149   let Inst{9-5}   = Rn;
4150   let Inst{4-0}   = Rt;
4152   let DecoderMethod = "DecodePairLdStInstruction";
4155 let hasSideEffects = 0 in {
4156 let mayStore = 0, mayLoad = 1 in
4157 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4158                      Operand indextype, string asm>
4159     : BaseLoadStorePairPreIdx<opc, V, 1,
4160                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4161                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
4162       Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4164 let mayStore = 1, mayLoad = 0 in
4165 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4166                       Operand indextype, string asm>
4167     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4168                              (ins regtype:$Rt, regtype:$Rt2,
4169                                   GPR64sp:$Rn, indextype:$offset),
4170                              asm>,
4171       Sched<[WriteAdr, WriteSTP]>;
4172 } // hasSideEffects = 0
4174 // (post-indexed)
4176 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4177                               string asm>
4178     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4179   bits<5> Rt;
4180   bits<5> Rt2;
4181   bits<5> Rn;
4182   bits<7> offset;
4183   let Inst{31-30} = opc;
4184   let Inst{29-27} = 0b101;
4185   let Inst{26}    = V;
4186   let Inst{25-23} = 0b001;
4187   let Inst{22}    = L;
4188   let Inst{21-15} = offset;
4189   let Inst{14-10} = Rt2;
4190   let Inst{9-5}   = Rn;
4191   let Inst{4-0}   = Rt;
4193   let DecoderMethod = "DecodePairLdStInstruction";
4196 let hasSideEffects = 0 in {
4197 let mayStore = 0, mayLoad = 1 in
4198 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4199                       Operand idxtype, string asm>
4200     : BaseLoadStorePairPostIdx<opc, V, 1,
4201                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4202                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4203       Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4205 let mayStore = 1, mayLoad = 0 in
4206 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4207                        Operand idxtype, string asm>
4208     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4209                              (ins regtype:$Rt, regtype:$Rt2,
4210                                   GPR64sp:$Rn, idxtype:$offset),
4211                              asm>,
4212       Sched<[WriteAdr, WriteSTP]>;
4213 } // hasSideEffects = 0
4215 //  (no-allocate)
4217 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4218                               string asm>
4219     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4220   bits<5> Rt;
4221   bits<5> Rt2;
4222   bits<5> Rn;
4223   bits<7> offset;
4224   let Inst{31-30} = opc;
4225   let Inst{29-27} = 0b101;
4226   let Inst{26}    = V;
4227   let Inst{25-23} = 0b000;
4228   let Inst{22}    = L;
4229   let Inst{21-15} = offset;
4230   let Inst{14-10} = Rt2;
4231   let Inst{9-5}   = Rn;
4232   let Inst{4-0}   = Rt;
4234   let DecoderMethod = "DecodePairLdStInstruction";
4237 multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4238                            Operand indextype, string asm> {
4239   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4240   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4241                                    (outs regtype:$Rt, regtype:$Rt2),
4242                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
4243           Sched<[WriteLD, WriteLDHi]>;
4246   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4247                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4248                                                   GPR64sp:$Rn, 0)>;
4251 multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4252                       Operand indextype, string asm> {
4253   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4254   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4255                                    (ins regtype:$Rt, regtype:$Rt2,
4256                                         GPR64sp:$Rn, indextype:$offset),
4257                                    asm>,
4258           Sched<[WriteSTP]>;
4260   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4261                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4262                                                   GPR64sp:$Rn, 0)>;
4265 //---
4266 // Load/store exclusive
4267 //---
4269 // True exclusive operations write to and/or read from the system's exclusive
4270 // monitors, which as far as a compiler is concerned can be modelled as a
4271 // random shared memory address. Hence LoadExclusive mayStore.
4273 // Since these instructions have the undefined register bits set to 1 in
4274 // their canonical form, we need a post encoder method to set those bits
4275 // to 1 when encoding these instructions. We do this using the
4276 // fixLoadStoreExclusive function. This function has template parameters:
4278 // fixLoadStoreExclusive<int hasRs, int hasRt2>
4280 // hasRs indicates that the instruction uses the Rs field, so we won't set
4281 // it to 1 (and the same for Rt2). We don't need template parameters for
4282 // the other register fields since Rt and Rn are always used.
4284 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4285 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4286                              dag oops, dag iops, string asm, string operands>
4287     : I<oops, iops, asm, operands, "", []> {
4288   let Inst{31-30} = sz;
4289   let Inst{29-24} = 0b001000;
4290   let Inst{23}    = o2;
4291   let Inst{22}    = L;
4292   let Inst{21}    = o1;
4293   let Inst{15}    = o0;
4295   let DecoderMethod = "DecodeExclusiveLdStInstruction";
4298 // Neither Rs nor Rt2 operands.
4299 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4300                                dag oops, dag iops, string asm, string operands>
4301     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4302   bits<5> Rt;
4303   bits<5> Rn;
4304   let Inst{20-16} = 0b11111;
4305   let Unpredictable{20-16} = 0b11111;
4306   let Inst{14-10} = 0b11111;
4307   let Unpredictable{14-10} = 0b11111;
4308   let Inst{9-5} = Rn;
4309   let Inst{4-0} = Rt;
4311   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4314 // Simple load acquires don't set the exclusive monitor
4315 let mayLoad = 1, mayStore = 0 in
4316 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4317                   RegisterClass regtype, string asm>
4318     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4319                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4320       Sched<[WriteLD]>;
4322 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4323                     RegisterClass regtype, string asm>
4324     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4325                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4326       Sched<[WriteLD]>;
4328 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4329                        RegisterClass regtype, string asm>
4330     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4331                              (outs regtype:$Rt, regtype:$Rt2),
4332                              (ins GPR64sp0:$Rn), asm,
4333                              "\t$Rt, $Rt2, [$Rn]">,
4334       Sched<[WriteLD, WriteLDHi]> {
4335   bits<5> Rt;
4336   bits<5> Rt2;
4337   bits<5> Rn;
4338   let Inst{14-10} = Rt2;
4339   let Inst{9-5} = Rn;
4340   let Inst{4-0} = Rt;
4342   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4345 // Simple store release operations do not check the exclusive monitor.
4346 let mayLoad = 0, mayStore = 1 in
4347 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4348                    RegisterClass regtype, string asm>
4349     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4350                                (ins regtype:$Rt, GPR64sp0:$Rn),
4351                                asm, "\t$Rt, [$Rn]">,
4352       Sched<[WriteST]>;
4354 let mayLoad = 1, mayStore = 1 in
4355 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4356                      RegisterClass regtype, string asm>
4357     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4358                              (ins regtype:$Rt, GPR64sp0:$Rn),
4359                              asm, "\t$Ws, $Rt, [$Rn]">,
4360       Sched<[WriteSTX]> {
4361   bits<5> Ws;
4362   bits<5> Rt;
4363   bits<5> Rn;
4364   let Inst{20-16} = Ws;
4365   let Inst{9-5} = Rn;
4366   let Inst{4-0} = Rt;
4368   let Constraints = "@earlyclobber $Ws";
4369   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4372 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4373                          RegisterClass regtype, string asm>
4374     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4375                              (outs GPR32:$Ws),
4376                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4377                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4378       Sched<[WriteSTX]> {
4379   bits<5> Ws;
4380   bits<5> Rt;
4381   bits<5> Rt2;
4382   bits<5> Rn;
4383   let Inst{20-16} = Ws;
4384   let Inst{14-10} = Rt2;
4385   let Inst{9-5} = Rn;
4386   let Inst{4-0} = Rt;
4388   let Constraints = "@earlyclobber $Ws";
4391 // Armv8.5-A Memory Tagging Extension
4392 class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4393                  string asm_opnds, string cstr, dag oops, dag iops>
4394     : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4395       Sched<[]> {
4396   bits<5> Rn;
4398   let Inst{31-24} = 0b11011001;
4399   let Inst{23-22} = opc1;
4400   let Inst{21}    = 1;
4401   // Inst{20-12} defined by subclass
4402   let Inst{11-10} = opc2;
4403   let Inst{9-5}   = Rn;
4404   // Inst{4-0} defined by subclass
4407 class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4408                    dag oops, dag iops>
4409     : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4410                   "", oops, iops> {
4411   bits<5> Rt;
4413   let Inst{20-12} = 0b000000000;
4414   let Inst{4-0}   = Rt;
4416   let mayLoad = Load;
4419 class MemTagLoad<string asm_insn, string asm_opnds>
4420     : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4421                  (outs GPR64:$wback),
4422                  (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4423   bits<5> Rt;
4424   bits<9> offset;
4426   let Inst{20-12} = offset;
4427   let Inst{4-0}   = Rt;
4429   let mayLoad = 1;
4432 class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4433                      string asm_opnds, string cstr, dag oops, dag iops>
4434     : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4435   bits<5> Rt;
4436   bits<9> offset;
4438   let Inst{20-12} = offset;
4439   let Inst{4-0}   = Rt;
4441   let mayStore = 1;
4444 multiclass MemTagStore<bits<2> opc1, string insn> {
4445   def Offset :
4446     BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4447                     (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4448   def PreIndex :
4449     BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4450                     "$Rn = $wback",
4451                     (outs GPR64sp:$wback),
4452                     (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4453   def PostIndex :
4454     BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4455                     "$Rn = $wback",
4456                     (outs GPR64sp:$wback),
4457                     (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4459   def : InstAlias<insn # "\t$Rt, [$Rn]",
4460                   (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4463 //---
4464 // Exception generation
4465 //---
4467 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4468 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4469     : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4470       Sched<[WriteSys]> {
4471   bits<16> imm;
4472   let Inst{31-24} = 0b11010100;
4473   let Inst{23-21} = op1;
4474   let Inst{20-5}  = imm;
4475   let Inst{4-2}   = 0b000;
4476   let Inst{1-0}   = ll;
4479 //---
4480 // UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4481 //--
4482 let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4483 class UDFType<bits<16> opc, string asm>
4484   : I<(outs), (ins uimm16:$imm),
4485        asm, "\t$imm", "", []>,
4486     Sched<[]> {
4487   bits<16> imm;
4488   let Inst{31-16} = opc;
4489   let Inst{15-0} = imm;
4492 let Predicates = [HasFPARMv8] in {
4494 //---
4495 // Floating point to integer conversion
4496 //---
4498 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4499                       RegisterClass srcType, RegisterClass dstType,
4500                       string asm, list<dag> pattern>
4501     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4502          asm, "\t$Rd, $Rn", "", pattern>,
4503       Sched<[WriteFCvt]> {
4504   bits<5> Rd;
4505   bits<5> Rn;
4506   let Inst{30-29} = 0b00;
4507   let Inst{28-24} = 0b11110;
4508   let Inst{23-22} = type;
4509   let Inst{21}    = 1;
4510   let Inst{20-19} = rmode;
4511   let Inst{18-16} = opcode;
4512   let Inst{15-10} = 0;
4513   let Inst{9-5}   = Rn;
4514   let Inst{4-0}   = Rd;
4517 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4518 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4519                       RegisterClass srcType, RegisterClass dstType,
4520                       Operand immType, string asm, list<dag> pattern>
4521     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4522          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4523       Sched<[WriteFCvt]> {
4524   bits<5> Rd;
4525   bits<5> Rn;
4526   bits<6> scale;
4527   let Inst{30-29} = 0b00;
4528   let Inst{28-24} = 0b11110;
4529   let Inst{23-22} = type;
4530   let Inst{21}    = 0;
4531   let Inst{20-19} = rmode;
4532   let Inst{18-16} = opcode;
4533   let Inst{15-10} = scale;
4534   let Inst{9-5}   = Rn;
4535   let Inst{4-0}   = Rd;
4538 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4539            SDPatternOperator OpN> {
4540   // Unscaled half-precision to 32-bit
4541   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4542                                      [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4543     let Inst{31} = 0; // 32-bit GPR flag
4544     let Predicates = [HasFullFP16];
4545   }
4547   // Unscaled half-precision to 64-bit
4548   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4549                                      [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4550     let Inst{31} = 1; // 64-bit GPR flag
4551     let Predicates = [HasFullFP16];
4552   }
4554   // Unscaled single-precision to 32-bit
4555   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4556                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4557     let Inst{31} = 0; // 32-bit GPR flag
4558   }
4560   // Unscaled single-precision to 64-bit
4561   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4562                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4563     let Inst{31} = 1; // 64-bit GPR flag
4564   }
4566   // Unscaled double-precision to 32-bit
4567   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4568                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4569     let Inst{31} = 0; // 32-bit GPR flag
4570   }
4572   // Unscaled double-precision to 64-bit
4573   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4574                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4575     let Inst{31} = 1; // 64-bit GPR flag
4576   }
4579 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4580                              SDPatternOperator OpN> {
4581   // Scaled half-precision to 32-bit
4582   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4583                               fixedpoint_f16_i32, asm,
4584               [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4585                                           fixedpoint_f16_i32:$scale)))]> {
4586     let Inst{31} = 0; // 32-bit GPR flag
4587     let scale{5} = 1;
4588     let Predicates = [HasFullFP16];
4589   }
4591   // Scaled half-precision to 64-bit
4592   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4593                               fixedpoint_f16_i64, asm,
4594               [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4595                                           fixedpoint_f16_i64:$scale)))]> {
4596     let Inst{31} = 1; // 64-bit GPR flag
4597     let Predicates = [HasFullFP16];
4598   }
4600   // Scaled single-precision to 32-bit
4601   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4602                               fixedpoint_f32_i32, asm,
4603               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4604                                           fixedpoint_f32_i32:$scale)))]> {
4605     let Inst{31} = 0; // 32-bit GPR flag
4606     let scale{5} = 1;
4607   }
4609   // Scaled single-precision to 64-bit
4610   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4611                               fixedpoint_f32_i64, asm,
4612               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4613                                           fixedpoint_f32_i64:$scale)))]> {
4614     let Inst{31} = 1; // 64-bit GPR flag
4615   }
4617   // Scaled double-precision to 32-bit
4618   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4619                               fixedpoint_f64_i32, asm,
4620               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4621                                           fixedpoint_f64_i32:$scale)))]> {
4622     let Inst{31} = 0; // 32-bit GPR flag
4623     let scale{5} = 1;
4624   }
4626   // Scaled double-precision to 64-bit
4627   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4628                               fixedpoint_f64_i64, asm,
4629               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4630                                           fixedpoint_f64_i64:$scale)))]> {
4631     let Inst{31} = 1; // 64-bit GPR flag
4632   }
4635 //---
4636 // Integer to floating point conversion
4637 //---
4639 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4640 class BaseIntegerToFP<bit isUnsigned,
4641                       RegisterClass srcType, RegisterClass dstType,
4642                       Operand immType, string asm, list<dag> pattern>
4643     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4644          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4645       Sched<[WriteFCvt]> {
4646   bits<5> Rd;
4647   bits<5> Rn;
4648   bits<6> scale;
4649   let Inst{30-24} = 0b0011110;
4650   let Inst{21-17} = 0b00001;
4651   let Inst{16}    = isUnsigned;
4652   let Inst{15-10} = scale;
4653   let Inst{9-5}   = Rn;
4654   let Inst{4-0}   = Rd;
4657 class BaseIntegerToFPUnscaled<bit isUnsigned,
4658                       RegisterClass srcType, RegisterClass dstType,
4659                       ValueType dvt, string asm, SDPatternOperator node>
4660     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4661          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4662       Sched<[WriteFCvt]> {
4663   bits<5> Rd;
4664   bits<5> Rn;
4665   bits<6> scale;
4666   let Inst{30-24} = 0b0011110;
4667   let Inst{21-17} = 0b10001;
4668   let Inst{16}    = isUnsigned;
4669   let Inst{15-10} = 0b000000;
4670   let Inst{9-5}   = Rn;
4671   let Inst{4-0}   = Rd;
4674 multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4675   // Unscaled
4676   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4677     let Inst{31} = 0; // 32-bit GPR flag
4678     let Inst{23-22} = 0b11; // 16-bit FPR flag
4679     let Predicates = [HasFullFP16];
4680   }
4682   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4683     let Inst{31} = 0; // 32-bit GPR flag
4684     let Inst{23-22} = 0b00; // 32-bit FPR flag
4685   }
4687   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4688     let Inst{31} = 0; // 32-bit GPR flag
4689     let Inst{23-22} = 0b01; // 64-bit FPR flag
4690   }
4692   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4693     let Inst{31} = 1; // 64-bit GPR flag
4694     let Inst{23-22} = 0b11; // 16-bit FPR flag
4695     let Predicates = [HasFullFP16];
4696   }
4698   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4699     let Inst{31} = 1; // 64-bit GPR flag
4700     let Inst{23-22} = 0b00; // 32-bit FPR flag
4701   }
4703   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4704     let Inst{31} = 1; // 64-bit GPR flag
4705     let Inst{23-22} = 0b01; // 64-bit FPR flag
4706   }
4708   // Scaled
4709   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4710                              [(set (f16 FPR16:$Rd),
4711                                    (fdiv (node GPR32:$Rn),
4712                                          fixedpoint_f16_i32:$scale))]> {
4713     let Inst{31} = 0; // 32-bit GPR flag
4714     let Inst{23-22} = 0b11; // 16-bit FPR flag
4715     let scale{5} = 1;
4716     let Predicates = [HasFullFP16];
4717   }
4719   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4720                              [(set FPR32:$Rd,
4721                                    (fdiv (node GPR32:$Rn),
4722                                          fixedpoint_f32_i32:$scale))]> {
4723     let Inst{31} = 0; // 32-bit GPR flag
4724     let Inst{23-22} = 0b00; // 32-bit FPR flag
4725     let scale{5} = 1;
4726   }
4728   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4729                              [(set FPR64:$Rd,
4730                                    (fdiv (node GPR32:$Rn),
4731                                          fixedpoint_f64_i32:$scale))]> {
4732     let Inst{31} = 0; // 32-bit GPR flag
4733     let Inst{23-22} = 0b01; // 64-bit FPR flag
4734     let scale{5} = 1;
4735   }
4737   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4738                              [(set (f16 FPR16:$Rd),
4739                                    (fdiv (node GPR64:$Rn),
4740                                          fixedpoint_f16_i64:$scale))]> {
4741     let Inst{31} = 1; // 64-bit GPR flag
4742     let Inst{23-22} = 0b11; // 16-bit FPR flag
4743     let Predicates = [HasFullFP16];
4744   }
4746   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4747                              [(set FPR32:$Rd,
4748                                    (fdiv (node GPR64:$Rn),
4749                                          fixedpoint_f32_i64:$scale))]> {
4750     let Inst{31} = 1; // 64-bit GPR flag
4751     let Inst{23-22} = 0b00; // 32-bit FPR flag
4752   }
4754   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4755                              [(set FPR64:$Rd,
4756                                    (fdiv (node GPR64:$Rn),
4757                                          fixedpoint_f64_i64:$scale))]> {
4758     let Inst{31} = 1; // 64-bit GPR flag
4759     let Inst{23-22} = 0b01; // 64-bit FPR flag
4760   }
4763 //---
4764 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4765 //---
4767 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4768 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4769                       RegisterClass srcType, RegisterClass dstType,
4770                       string asm>
4771     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4772         // We use COPY_TO_REGCLASS for these bitconvert operations.
4773         // copyPhysReg() expands the resultant COPY instructions after
4774         // regalloc is done. This gives greater freedom for the allocator
4775         // and related passes (coalescing, copy propagation, et. al.) to
4776         // be more effective.
4777         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4778       Sched<[WriteFCopy]> {
4779   bits<5> Rd;
4780   bits<5> Rn;
4781   let Inst{30-24} = 0b0011110;
4782   let Inst{21}    = 1;
4783   let Inst{20-19} = rmode;
4784   let Inst{18-16} = opcode;
4785   let Inst{15-10} = 0b000000;
4786   let Inst{9-5}   = Rn;
4787   let Inst{4-0}   = Rd;
4790 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4791 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4792                      RegisterClass srcType, RegisterOperand dstType, string asm,
4793                      string kind>
4794     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4795         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4796       Sched<[WriteFCopy]> {
4797   bits<5> Rd;
4798   bits<5> Rn;
4799   let Inst{30-23} = 0b00111101;
4800   let Inst{21}    = 1;
4801   let Inst{20-19} = rmode;
4802   let Inst{18-16} = opcode;
4803   let Inst{15-10} = 0b000000;
4804   let Inst{9-5}   = Rn;
4805   let Inst{4-0}   = Rd;
4807   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4810 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4811 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4812                      RegisterOperand srcType, RegisterClass dstType, string asm,
4813                      string kind>
4814     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4815         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4816       Sched<[WriteFCopy]> {
4817   bits<5> Rd;
4818   bits<5> Rn;
4819   let Inst{30-23} = 0b00111101;
4820   let Inst{21}    = 1;
4821   let Inst{20-19} = rmode;
4822   let Inst{18-16} = opcode;
4823   let Inst{15-10} = 0b000000;
4824   let Inst{9-5}   = Rn;
4825   let Inst{4-0}   = Rd;
4827   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4831 multiclass UnscaledConversion<string asm> {
4832   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4833     let Inst{31} = 0; // 32-bit GPR flag
4834     let Inst{23-22} = 0b11; // 16-bit FPR flag
4835     let Predicates = [HasFullFP16];
4836   }
4838   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4839     let Inst{31} = 1; // 64-bit GPR flag
4840     let Inst{23-22} = 0b11; // 16-bit FPR flag
4841     let Predicates = [HasFullFP16];
4842   }
4844   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4845     let Inst{31} = 0; // 32-bit GPR flag
4846     let Inst{23-22} = 0b00; // 32-bit FPR flag
4847   }
4849   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4850     let Inst{31} = 1; // 64-bit GPR flag
4851     let Inst{23-22} = 0b01; // 64-bit FPR flag
4852   }
4854   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4855     let Inst{31} = 0; // 32-bit GPR flag
4856     let Inst{23-22} = 0b11; // 16-bit FPR flag
4857     let Predicates = [HasFullFP16];
4858   }
4860   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4861     let Inst{31} = 1; // 64-bit GPR flag
4862     let Inst{23-22} = 0b11; // 16-bit FPR flag
4863     let Predicates = [HasFullFP16];
4864   }
4866   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4867     let Inst{31} = 0; // 32-bit GPR flag
4868     let Inst{23-22} = 0b00; // 32-bit FPR flag
4869   }
4871   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4872     let Inst{31} = 1; // 64-bit GPR flag
4873     let Inst{23-22} = 0b01; // 64-bit FPR flag
4874   }
4876   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4877                                              asm, ".d"> {
4878     let Inst{31} = 1;
4879     let Inst{22} = 0;
4880   }
4882   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4883                                                asm, ".d"> {
4884     let Inst{31} = 1;
4885     let Inst{22} = 0;
4886   }
4889 //---
4890 // Floating point conversion
4891 //---
4893 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4894                        RegisterClass srcType, string asm, list<dag> pattern>
4895     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4896       Sched<[WriteFCvt]> {
4897   bits<5> Rd;
4898   bits<5> Rn;
4899   let Inst{31-24} = 0b00011110;
4900   let Inst{23-22} = type;
4901   let Inst{21-17} = 0b10001;
4902   let Inst{16-15} = opcode;
4903   let Inst{14-10} = 0b10000;
4904   let Inst{9-5}   = Rn;
4905   let Inst{4-0}   = Rd;
4908 multiclass FPConversion<string asm> {
4909   // Double-precision to Half-precision
4910   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4911                              [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4913   // Double-precision to Single-precision
4914   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4915                              [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4917   // Half-precision to Double-precision
4918   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4919                              [(set FPR64:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4921   // Half-precision to Single-precision
4922   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4923                              [(set FPR32:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4925   // Single-precision to Double-precision
4926   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4927                              [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4929   // Single-precision to Half-precision
4930   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4931                              [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
4934 //---
4935 // Single operand floating point data processing
4936 //---
4938 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4939 class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4940                               ValueType vt, string asm, SDPatternOperator node>
4941     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4942          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4943       Sched<[WriteF]> {
4944   bits<5> Rd;
4945   bits<5> Rn;
4946   let Inst{31-24} = 0b00011110;
4947   let Inst{21}    = 0b1;
4948   let Inst{20-15} = opcode;
4949   let Inst{14-10} = 0b10000;
4950   let Inst{9-5}   = Rn;
4951   let Inst{4-0}   = Rd;
4954 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4955                                SDPatternOperator node = null_frag> {
4957   def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4958     let Inst{23-22} = 0b11; // 16-bit size flag
4959     let Predicates = [HasFullFP16];
4960   }
4962   def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4963     let Inst{23-22} = 0b00; // 32-bit size flag
4964   }
4966   def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4967     let Inst{23-22} = 0b01; // 64-bit size flag
4968   }
4971 multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4972                   SDPatternOperator node = null_frag>{
4974   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4975     let Inst{23-22} = 0b00; // 32-bit registers
4976   }
4978   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4979     let Inst{23-22} = 0b01; // 64-bit registers
4980   }
4983 // FRInt[32|64][Z|N] instructions
4984 multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4985       SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4987 //---
4988 // Two operand floating point data processing
4989 //---
4991 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4992 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4993                            string asm, list<dag> pat>
4994     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4995          asm, "\t$Rd, $Rn, $Rm", "", pat>,
4996       Sched<[WriteF]> {
4997   bits<5> Rd;
4998   bits<5> Rn;
4999   bits<5> Rm;
5000   let Inst{31-24} = 0b00011110;
5001   let Inst{21}    = 1;
5002   let Inst{20-16} = Rm;
5003   let Inst{15-12} = opcode;
5004   let Inst{11-10} = 0b10;
5005   let Inst{9-5}   = Rn;
5006   let Inst{4-0}   = Rd;
5009 multiclass TwoOperandFPData<bits<4> opcode, string asm,
5010                             SDPatternOperator node = null_frag> {
5011   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5012                          [(set (f16 FPR16:$Rd),
5013                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5014     let Inst{23-22} = 0b11; // 16-bit size flag
5015     let Predicates = [HasFullFP16];
5016   }
5018   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5019                          [(set (f32 FPR32:$Rd),
5020                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5021     let Inst{23-22} = 0b00; // 32-bit size flag
5022   }
5024   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5025                          [(set (f64 FPR64:$Rd),
5026                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5027     let Inst{23-22} = 0b01; // 64-bit size flag
5028   }
5031 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
5032   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5033                   [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5034     let Inst{23-22} = 0b11; // 16-bit size flag
5035     let Predicates = [HasFullFP16];
5036   }
5038   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5039                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5040     let Inst{23-22} = 0b00; // 32-bit size flag
5041   }
5043   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5044                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5045     let Inst{23-22} = 0b01; // 64-bit size flag
5046   }
5050 //---
5051 // Three operand floating point data processing
5052 //---
5054 class BaseThreeOperandFPData<bit isNegated, bit isSub,
5055                              RegisterClass regtype, string asm, list<dag> pat>
5056     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5057          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5058       Sched<[WriteFMul]> {
5059   bits<5> Rd;
5060   bits<5> Rn;
5061   bits<5> Rm;
5062   bits<5> Ra;
5063   let Inst{31-24} = 0b00011111;
5064   let Inst{21}    = isNegated;
5065   let Inst{20-16} = Rm;
5066   let Inst{15}    = isSub;
5067   let Inst{14-10} = Ra;
5068   let Inst{9-5}   = Rn;
5069   let Inst{4-0}   = Rd;
5072 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5073                               SDPatternOperator node> {
5074   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5075             [(set (f16 FPR16:$Rd),
5076                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5077     let Inst{23-22} = 0b11; // 16-bit size flag
5078     let Predicates = [HasFullFP16];
5079   }
5081   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5082             [(set FPR32:$Rd,
5083                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5084     let Inst{23-22} = 0b00; // 32-bit size flag
5085   }
5087   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5088             [(set FPR64:$Rd,
5089                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5090     let Inst{23-22} = 0b01; // 64-bit size flag
5091   }
5094 //---
5095 // Floating point data comparisons
5096 //---
5098 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5099 class BaseOneOperandFPComparison<bit signalAllNans,
5100                                  RegisterClass regtype, string asm,
5101                                  list<dag> pat>
5102     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5103       Sched<[WriteFCmp]> {
5104   bits<5> Rn;
5105   let Inst{31-24} = 0b00011110;
5106   let Inst{21}    = 1;
5108   let Inst{15-10} = 0b001000;
5109   let Inst{9-5}   = Rn;
5110   let Inst{4}     = signalAllNans;
5111   let Inst{3-0}   = 0b1000;
5113   // Rm should be 0b00000 canonically, but we need to accept any value.
5114   let PostEncoderMethod = "fixOneOperandFPComparison";
5117 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5118 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5119                                 string asm, list<dag> pat>
5120     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5121       Sched<[WriteFCmp]> {
5122   bits<5> Rm;
5123   bits<5> Rn;
5124   let Inst{31-24} = 0b00011110;
5125   let Inst{21}    = 1;
5126   let Inst{20-16} = Rm;
5127   let Inst{15-10} = 0b001000;
5128   let Inst{9-5}   = Rn;
5129   let Inst{4}     = signalAllNans;
5130   let Inst{3-0}   = 0b0000;
5133 multiclass FPComparison<bit signalAllNans, string asm,
5134                         SDPatternOperator OpNode = null_frag> {
5135   let Defs = [NZCV] in {
5136   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5137       [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5138     let Inst{23-22} = 0b11;
5139     let Predicates = [HasFullFP16];
5140   }
5142   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5143       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5144     let Inst{23-22} = 0b11;
5145     let Predicates = [HasFullFP16];
5146   }
5148   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5149       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5150     let Inst{23-22} = 0b00;
5151   }
5153   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5154       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5155     let Inst{23-22} = 0b00;
5156   }
5158   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5159       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5160     let Inst{23-22} = 0b01;
5161   }
5163   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5164       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5165     let Inst{23-22} = 0b01;
5166   }
5167   } // Defs = [NZCV]
5170 //---
5171 // Floating point conditional comparisons
5172 //---
5174 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5175 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5176                            string mnemonic, list<dag> pat>
5177     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5178          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5179       Sched<[WriteFCmp]> {
5180   let Uses = [NZCV];
5181   let Defs = [NZCV];
5183   bits<5> Rn;
5184   bits<5> Rm;
5185   bits<4> nzcv;
5186   bits<4> cond;
5188   let Inst{31-24} = 0b00011110;
5189   let Inst{21}    = 1;
5190   let Inst{20-16} = Rm;
5191   let Inst{15-12} = cond;
5192   let Inst{11-10} = 0b01;
5193   let Inst{9-5}   = Rn;
5194   let Inst{4}     = signalAllNans;
5195   let Inst{3-0}   = nzcv;
5198 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5199                             SDPatternOperator OpNode = null_frag> {
5200   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5201       [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5202                           (i32 imm:$cond), NZCV))]> {
5203     let Inst{23-22} = 0b11;
5204     let Predicates = [HasFullFP16];
5205   }
5207   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5208       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5209                           (i32 imm:$cond), NZCV))]> {
5210     let Inst{23-22} = 0b00;
5211   }
5213   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5214       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5215                           (i32 imm:$cond), NZCV))]> {
5216     let Inst{23-22} = 0b01;
5217   }
5220 //---
5221 // Floating point conditional select
5222 //---
5224 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5225     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5226          asm, "\t$Rd, $Rn, $Rm, $cond", "",
5227          [(set regtype:$Rd,
5228                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5229                           (i32 imm:$cond), NZCV))]>,
5230       Sched<[WriteF]> {
5231   bits<5> Rd;
5232   bits<5> Rn;
5233   bits<5> Rm;
5234   bits<4> cond;
5236   let Inst{31-24} = 0b00011110;
5237   let Inst{21}    = 1;
5238   let Inst{20-16} = Rm;
5239   let Inst{15-12} = cond;
5240   let Inst{11-10} = 0b11;
5241   let Inst{9-5}   = Rn;
5242   let Inst{4-0}   = Rd;
5245 multiclass FPCondSelect<string asm> {
5246   let Uses = [NZCV] in {
5247   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5248     let Inst{23-22} = 0b11;
5249     let Predicates = [HasFullFP16];
5250   }
5252   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5253     let Inst{23-22} = 0b00;
5254   }
5256   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5257     let Inst{23-22} = 0b01;
5258   }
5259   } // Uses = [NZCV]
5262 //---
5263 // Floating move immediate
5264 //---
5266 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5267   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5268       [(set regtype:$Rd, fpimmtype:$imm)]>,
5269     Sched<[WriteFImm]> {
5270   bits<5> Rd;
5271   bits<8> imm;
5272   let Inst{31-24} = 0b00011110;
5273   let Inst{21}    = 1;
5274   let Inst{20-13} = imm;
5275   let Inst{12-5}  = 0b10000000;
5276   let Inst{4-0}   = Rd;
5279 multiclass FPMoveImmediate<string asm> {
5280   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5281     let Inst{23-22} = 0b11;
5282     let Predicates = [HasFullFP16];
5283   }
5285   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5286     let Inst{23-22} = 0b00;
5287   }
5289   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5290     let Inst{23-22} = 0b01;
5291   }
5293 } // end of 'let Predicates = [HasFPARMv8]'
5295 //----------------------------------------------------------------------------
5296 // AdvSIMD
5297 //----------------------------------------------------------------------------
5299 let Predicates = [HasNEON] in {
5301 //----------------------------------------------------------------------------
5302 // AdvSIMD three register vector instructions
5303 //----------------------------------------------------------------------------
5305 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5306 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5307                         RegisterOperand regtype, string asm, string kind,
5308                         list<dag> pattern>
5309   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5310       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5311       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5312     Sched<[WriteV]> {
5313   bits<5> Rd;
5314   bits<5> Rn;
5315   bits<5> Rm;
5316   let Inst{31}    = 0;
5317   let Inst{30}    = Q;
5318   let Inst{29}    = U;
5319   let Inst{28-24} = 0b01110;
5320   let Inst{23-21} = size;
5321   let Inst{20-16} = Rm;
5322   let Inst{15-11} = opcode;
5323   let Inst{10}    = 1;
5324   let Inst{9-5}   = Rn;
5325   let Inst{4-0}   = Rd;
5328 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5329 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5330                         RegisterOperand regtype, string asm, string kind,
5331                         list<dag> pattern>
5332   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5333       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5334       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5335     Sched<[WriteV]> {
5336   bits<5> Rd;
5337   bits<5> Rn;
5338   bits<5> Rm;
5339   let Inst{31}    = 0;
5340   let Inst{30}    = Q;
5341   let Inst{29}    = U;
5342   let Inst{28-24} = 0b01110;
5343   let Inst{23-21} = size;
5344   let Inst{20-16} = Rm;
5345   let Inst{15-11} = opcode;
5346   let Inst{10}    = 1;
5347   let Inst{9-5}   = Rn;
5348   let Inst{4-0}   = Rd;
5351 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5352 class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5353   : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5354     Sched<[WriteV]>;
5356 multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5357   def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5358              [(set (v8i8 V64:$dst),
5359                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5360   def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5361              [(set (v16i8 V128:$dst),
5362                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5363                            (v16i8 V128:$Rm)))]>;
5365   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5366                            (v4i16 V64:$RHS))),
5367           (!cast<Instruction>(NAME#"v8i8")
5368             V64:$LHS, V64:$MHS, V64:$RHS)>;
5369   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5370                            (v2i32 V64:$RHS))),
5371           (!cast<Instruction>(NAME#"v8i8")
5372             V64:$LHS, V64:$MHS, V64:$RHS)>;
5373   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5374                            (v1i64 V64:$RHS))),
5375           (!cast<Instruction>(NAME#"v8i8")
5376             V64:$LHS, V64:$MHS, V64:$RHS)>;
5378   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5379                            (v8i16 V128:$RHS))),
5380       (!cast<Instruction>(NAME#"v16i8")
5381         V128:$LHS, V128:$MHS, V128:$RHS)>;
5382   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5383                            (v4i32 V128:$RHS))),
5384       (!cast<Instruction>(NAME#"v16i8")
5385         V128:$LHS, V128:$MHS, V128:$RHS)>;
5386   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5387                            (v2i64 V128:$RHS))),
5388       (!cast<Instruction>(NAME#"v16i8")
5389         V128:$LHS, V128:$MHS, V128:$RHS)>;
5392 // All operand sizes distinguished in the encoding.
5393 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5394                                SDPatternOperator OpNode> {
5395   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5396                                       asm, ".8b",
5397          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5398   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5399                                       asm, ".16b",
5400          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5401   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5402                                       asm, ".4h",
5403          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5404   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5405                                       asm, ".8h",
5406          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5407   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5408                                       asm, ".2s",
5409          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5410   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5411                                       asm, ".4s",
5412          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5413   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5414                                       asm, ".2d",
5415          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5418 multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5419   def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5420           (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5421   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5422           (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5423   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5424           (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5426   def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5427           (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5428   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5429           (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5430   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5431           (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5432   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5433           (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5436 // As above, but D sized elements unsupported.
5437 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5438                                   SDPatternOperator OpNode> {
5439   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5440                                       asm, ".8b",
5441         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5442   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5443                                       asm, ".16b",
5444         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5445   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5446                                       asm, ".4h",
5447         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5448   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5449                                       asm, ".8h",
5450         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5451   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5452                                       asm, ".2s",
5453         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5454   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5455                                       asm, ".4s",
5456         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5459 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5460                                   SDPatternOperator OpNode> {
5461   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5462                                       asm, ".8b",
5463       [(set (v8i8 V64:$dst),
5464             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5465   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5466                                       asm, ".16b",
5467       [(set (v16i8 V128:$dst),
5468             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5469   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5470                                       asm, ".4h",
5471       [(set (v4i16 V64:$dst),
5472             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5473   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5474                                       asm, ".8h",
5475       [(set (v8i16 V128:$dst),
5476             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5477   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5478                                       asm, ".2s",
5479       [(set (v2i32 V64:$dst),
5480             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5481   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5482                                       asm, ".4s",
5483       [(set (v4i32 V128:$dst),
5484             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5487 // As above, but only B sized elements supported.
5488 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5489                                 SDPatternOperator OpNode> {
5490   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5491                                       asm, ".8b",
5492     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5493   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5494                                       asm, ".16b",
5495     [(set (v16i8 V128:$Rd),
5496           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5499 // As above, but only floating point elements supported.
5500 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5501                                  string asm, SDPatternOperator OpNode> {
5502   let Predicates = [HasNEON, HasFullFP16] in {
5503   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5504                                       asm, ".4h",
5505         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5506   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5507                                       asm, ".8h",
5508         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5509   } // Predicates = [HasNEON, HasFullFP16]
5510   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5511                                       asm, ".2s",
5512         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5513   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5514                                       asm, ".4s",
5515         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5516   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5517                                       asm, ".2d",
5518         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5521 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5522                                     string asm,
5523                                     SDPatternOperator OpNode> {
5524   let Predicates = [HasNEON, HasFullFP16] in {
5525   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5526                                       asm, ".4h",
5527         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5528   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5529                                       asm, ".8h",
5530         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5531   } // Predicates = [HasNEON, HasFullFP16]
5532   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5533                                       asm, ".2s",
5534         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5535   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5536                                       asm, ".4s",
5537         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5538   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5539                                       asm, ".2d",
5540         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5543 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5544                                  string asm, SDPatternOperator OpNode> {
5545   let Predicates = [HasNEON, HasFullFP16] in {
5546   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5547                                       asm, ".4h",
5548      [(set (v4f16 V64:$dst),
5549            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5550   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5551                                       asm, ".8h",
5552      [(set (v8f16 V128:$dst),
5553            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5554   } // Predicates = [HasNEON, HasFullFP16]
5555   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5556                                       asm, ".2s",
5557      [(set (v2f32 V64:$dst),
5558            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5559   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5560                                       asm, ".4s",
5561      [(set (v4f32 V128:$dst),
5562            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5563   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5564                                       asm, ".2d",
5565      [(set (v2f64 V128:$dst),
5566            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5569 // As above, but D and B sized elements unsupported.
5570 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5571                                 SDPatternOperator OpNode> {
5572   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5573                                       asm, ".4h",
5574         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5575   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5576                                       asm, ".8h",
5577         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5578   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5579                                       asm, ".2s",
5580         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5581   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5582                                       asm, ".4s",
5583         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5586 // Logical three vector ops share opcode bits, and only use B sized elements.
5587 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5588                                   SDPatternOperator OpNode = null_frag> {
5589   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5590                                      asm, ".8b",
5591                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5592   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5593                                      asm, ".16b",
5594                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5596   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5597           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5598   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5599           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5600   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5601           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5603   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5604       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5605   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5606       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5607   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5608       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5611 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5612                                   string asm, SDPatternOperator OpNode = null_frag> {
5613   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5614                                      asm, ".8b",
5615              [(set (v8i8 V64:$dst),
5616                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5617   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5618                                      asm, ".16b",
5619              [(set (v16i8 V128:$dst),
5620                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5621                            (v16i8 V128:$Rm)))]>;
5623   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5624                            (v4i16 V64:$RHS))),
5625           (!cast<Instruction>(NAME#"v8i8")
5626             V64:$LHS, V64:$MHS, V64:$RHS)>;
5627   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5628                            (v2i32 V64:$RHS))),
5629           (!cast<Instruction>(NAME#"v8i8")
5630             V64:$LHS, V64:$MHS, V64:$RHS)>;
5631   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5632                            (v1i64 V64:$RHS))),
5633           (!cast<Instruction>(NAME#"v8i8")
5634             V64:$LHS, V64:$MHS, V64:$RHS)>;
5636   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5637                            (v8i16 V128:$RHS))),
5638       (!cast<Instruction>(NAME#"v16i8")
5639         V128:$LHS, V128:$MHS, V128:$RHS)>;
5640   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5641                            (v4i32 V128:$RHS))),
5642       (!cast<Instruction>(NAME#"v16i8")
5643         V128:$LHS, V128:$MHS, V128:$RHS)>;
5644   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5645                            (v2i64 V128:$RHS))),
5646       (!cast<Instruction>(NAME#"v16i8")
5647         V128:$LHS, V128:$MHS, V128:$RHS)>;
5650 // ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5651 // bytes from S-sized elements.
5652 class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5653                                  string kind2, RegisterOperand RegType,
5654                                  ValueType AccumType, ValueType InputType,
5655                                  SDPatternOperator OpNode> :
5656         BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5657         [(set (AccumType RegType:$dst),
5658               (OpNode (AccumType RegType:$Rd),
5659                       (InputType RegType:$Rn),
5660                       (InputType RegType:$Rm)))]> {
5661   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5664 multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5665   def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5666                                          v2i32, v8i8, OpNode>;
5667   def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5668                                          v4i32, v16i8, OpNode>;
5671 // ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5672 // select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5673 // 8H to 4S, when Q=1).
5674 class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5675                                  string kind2, RegisterOperand RegType,
5676                                  ValueType AccumType, ValueType InputType,
5677                                  SDPatternOperator OpNode> :
5678         BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5679                 [(set (AccumType RegType:$dst),
5680               (OpNode (AccumType RegType:$Rd),
5681                       (InputType RegType:$Rn),
5682                       (InputType RegType:$Rm)))]> {
5683   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5684   let Inst{13} = b13;
5687 multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5688                                   SDPatternOperator OpNode> {
5689   def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5690                                          v2f32, v4f16, OpNode>;
5691   def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5692                                          v4f32, v8f16, OpNode>;
5696 //----------------------------------------------------------------------------
5697 // AdvSIMD two register vector instructions.
5698 //----------------------------------------------------------------------------
5700 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5701 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5702                             bits<2> size2, RegisterOperand regtype, string asm,
5703                             string dstkind, string srckind, list<dag> pattern>
5704   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5705       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5706       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5707     Sched<[WriteV]> {
5708   bits<5> Rd;
5709   bits<5> Rn;
5710   let Inst{31}    = 0;
5711   let Inst{30}    = Q;
5712   let Inst{29}    = U;
5713   let Inst{28-24} = 0b01110;
5714   let Inst{23-22} = size;
5715   let Inst{21} = 0b1;
5716   let Inst{20-19} = size2;
5717   let Inst{18-17} = 0b00;
5718   let Inst{16-12} = opcode;
5719   let Inst{11-10} = 0b10;
5720   let Inst{9-5}   = Rn;
5721   let Inst{4-0}   = Rd;
5724 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5725 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5726                                 bits<2> size2, RegisterOperand regtype,
5727                                 string asm, string dstkind, string srckind,
5728                                 list<dag> pattern>
5729   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5730       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5731       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5732     Sched<[WriteV]> {
5733   bits<5> Rd;
5734   bits<5> Rn;
5735   let Inst{31}    = 0;
5736   let Inst{30}    = Q;
5737   let Inst{29}    = U;
5738   let Inst{28-24} = 0b01110;
5739   let Inst{23-22} = size;
5740   let Inst{21} = 0b1;
5741   let Inst{20-19} = size2;
5742   let Inst{18-17} = 0b00;
5743   let Inst{16-12} = opcode;
5744   let Inst{11-10} = 0b10;
5745   let Inst{9-5}   = Rn;
5746   let Inst{4-0}   = Rd;
5749 // Supports B, H, and S element sizes.
5750 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5751                             SDPatternOperator OpNode> {
5752   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5753                                       asm, ".8b", ".8b",
5754                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5755   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5756                                       asm, ".16b", ".16b",
5757                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5758   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5759                                       asm, ".4h", ".4h",
5760                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5761   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5762                                       asm, ".8h", ".8h",
5763                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5764   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5765                                       asm, ".2s", ".2s",
5766                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5767   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5768                                       asm, ".4s", ".4s",
5769                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5772 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5773                             RegisterOperand regtype, string asm, string dstkind,
5774                             string srckind, string amount>
5775   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5776       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5777       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5778     Sched<[WriteV]> {
5779   bits<5> Rd;
5780   bits<5> Rn;
5781   let Inst{31}    = 0;
5782   let Inst{30}    = Q;
5783   let Inst{29-24} = 0b101110;
5784   let Inst{23-22} = size;
5785   let Inst{21-10} = 0b100001001110;
5786   let Inst{9-5}   = Rn;
5787   let Inst{4-0}   = Rd;
5790 multiclass SIMDVectorLShiftLongBySizeBHS {
5791   let hasSideEffects = 0 in {
5792   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5793                                              "shll", ".8h",  ".8b", "8">;
5794   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5795                                              "shll2", ".8h", ".16b", "8">;
5796   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5797                                              "shll", ".4s",  ".4h", "16">;
5798   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5799                                              "shll2", ".4s", ".8h", "16">;
5800   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5801                                              "shll", ".2d",  ".2s", "32">;
5802   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5803                                              "shll2", ".2d", ".4s", "32">;
5804   }
5807 // Supports all element sizes.
5808 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5809                              SDPatternOperator OpNode> {
5810   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5811                                       asm, ".4h", ".8b",
5812                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5813   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5814                                       asm, ".8h", ".16b",
5815                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5816   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5817                                       asm, ".2s", ".4h",
5818                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5819   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5820                                       asm, ".4s", ".8h",
5821                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5822   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5823                                       asm, ".1d", ".2s",
5824                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5825   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5826                                       asm, ".2d", ".4s",
5827                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5830 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5831                                  SDPatternOperator OpNode> {
5832   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5833                                           asm, ".4h", ".8b",
5834       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5835                                       (v8i8 V64:$Rn)))]>;
5836   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5837                                           asm, ".8h", ".16b",
5838       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5839                                       (v16i8 V128:$Rn)))]>;
5840   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5841                                           asm, ".2s", ".4h",
5842       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5843                                       (v4i16 V64:$Rn)))]>;
5844   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5845                                           asm, ".4s", ".8h",
5846       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5847                                       (v8i16 V128:$Rn)))]>;
5848   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5849                                           asm, ".1d", ".2s",
5850       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5851                                       (v2i32 V64:$Rn)))]>;
5852   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5853                                           asm, ".2d", ".4s",
5854       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5855                                       (v4i32 V128:$Rn)))]>;
5858 // Supports all element sizes, except 1xD.
5859 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5860                                   SDPatternOperator OpNode> {
5861   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5862                                     asm, ".8b", ".8b",
5863     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5864   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5865                                     asm, ".16b", ".16b",
5866     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5867   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5868                                     asm, ".4h", ".4h",
5869     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5870   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5871                                     asm, ".8h", ".8h",
5872     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5873   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5874                                     asm, ".2s", ".2s",
5875     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5876   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5877                                     asm, ".4s", ".4s",
5878     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5879   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5880                                     asm, ".2d", ".2d",
5881     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5884 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5885                              SDPatternOperator OpNode = null_frag> {
5886   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5887                                 asm, ".8b", ".8b",
5888     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5889   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5890                                 asm, ".16b", ".16b",
5891     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5892   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5893                                 asm, ".4h", ".4h",
5894     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5895   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5896                                 asm, ".8h", ".8h",
5897     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5898   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5899                                 asm, ".2s", ".2s",
5900     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5901   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5902                                 asm, ".4s", ".4s",
5903     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5904   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5905                                 asm, ".2d", ".2d",
5906     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5910 // Supports only B element sizes.
5911 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5912                           SDPatternOperator OpNode> {
5913   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5914                                 asm, ".8b", ".8b",
5915                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5916   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5917                                 asm, ".16b", ".16b",
5918                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5922 // Supports only B and H element sizes.
5923 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5924                                 SDPatternOperator OpNode> {
5925   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5926                                 asm, ".8b", ".8b",
5927                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5928   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5929                                 asm, ".16b", ".16b",
5930                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5931   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5932                                 asm, ".4h", ".4h",
5933                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5934   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5935                                 asm, ".8h", ".8h",
5936                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5939 // Supports H, S and D element sizes, uses high bit of the size field
5940 // as an extra opcode bit.
5941 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5942                            SDPatternOperator OpNode> {
5943   let Predicates = [HasNEON, HasFullFP16] in {
5944   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5945                                 asm, ".4h", ".4h",
5946                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5947   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5948                                 asm, ".8h", ".8h",
5949                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5950   } // Predicates = [HasNEON, HasFullFP16]
5951   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5952                                 asm, ".2s", ".2s",
5953                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5954   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5955                                 asm, ".4s", ".4s",
5956                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5957   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5958                                 asm, ".2d", ".2d",
5959                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5962 // Supports only S and D element sizes
5963 multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5964                            SDPatternOperator OpNode = null_frag> {
5966   def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5967                                 asm, ".2s", ".2s",
5968                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5969   def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5970                                 asm, ".4s", ".4s",
5971                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5972   def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5973                                 asm, ".2d", ".2d",
5974                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5977 multiclass FRIntNNTVector<bit U, bit op, string asm,
5978                           SDPatternOperator OpNode = null_frag> :
5979            SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5981 // Supports only S element size.
5982 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5983                            SDPatternOperator OpNode> {
5984   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5985                                 asm, ".2s", ".2s",
5986                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5987   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5988                                 asm, ".4s", ".4s",
5989                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5993 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5994                            SDPatternOperator OpNode> {
5995   let Predicates = [HasNEON, HasFullFP16] in {
5996   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5997                                 asm, ".4h", ".4h",
5998                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5999   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6000                                 asm, ".8h", ".8h",
6001                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6002   } // Predicates = [HasNEON, HasFullFP16]
6003   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6004                                 asm, ".2s", ".2s",
6005                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6006   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6007                                 asm, ".4s", ".4s",
6008                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6009   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6010                                 asm, ".2d", ".2d",
6011                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6014 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6015                            SDPatternOperator OpNode> {
6016   let Predicates = [HasNEON, HasFullFP16] in {
6017   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6018                                 asm, ".4h", ".4h",
6019                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6020   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6021                                 asm, ".8h", ".8h",
6022                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6023   } // Predicates = [HasNEON, HasFullFP16]
6024   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6025                                 asm, ".2s", ".2s",
6026                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6027   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6028                                 asm, ".4s", ".4s",
6029                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6030   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6031                                 asm, ".2d", ".2d",
6032                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6036 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6037                            RegisterOperand inreg, RegisterOperand outreg,
6038                            string asm, string outkind, string inkind,
6039                            list<dag> pattern>
6040   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6041       "{\t$Rd" # outkind # ", $Rn" # inkind #
6042       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6043     Sched<[WriteV]> {
6044   bits<5> Rd;
6045   bits<5> Rn;
6046   let Inst{31}    = 0;
6047   let Inst{30}    = Q;
6048   let Inst{29}    = U;
6049   let Inst{28-24} = 0b01110;
6050   let Inst{23-22} = size;
6051   let Inst{21-17} = 0b10000;
6052   let Inst{16-12} = opcode;
6053   let Inst{11-10} = 0b10;
6054   let Inst{9-5}   = Rn;
6055   let Inst{4-0}   = Rd;
6058 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6059                            RegisterOperand inreg, RegisterOperand outreg,
6060                            string asm, string outkind, string inkind,
6061                            list<dag> pattern>
6062   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6063       "{\t$Rd" # outkind # ", $Rn" # inkind #
6064       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6065     Sched<[WriteV]> {
6066   bits<5> Rd;
6067   bits<5> Rn;
6068   let Inst{31}    = 0;
6069   let Inst{30}    = Q;
6070   let Inst{29}    = U;
6071   let Inst{28-24} = 0b01110;
6072   let Inst{23-22} = size;
6073   let Inst{21-17} = 0b10000;
6074   let Inst{16-12} = opcode;
6075   let Inst{11-10} = 0b10;
6076   let Inst{9-5}   = Rn;
6077   let Inst{4-0}   = Rd;
6080 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6081                               SDPatternOperator OpNode> {
6082   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6083                                       asm, ".8b", ".8h",
6084         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6085   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6086                                       asm#"2", ".16b", ".8h", []>;
6087   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6088                                       asm, ".4h", ".4s",
6089         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6090   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6091                                       asm#"2", ".8h", ".4s", []>;
6092   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6093                                       asm, ".2s", ".2d",
6094         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6095   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6096                                       asm#"2", ".4s", ".2d", []>;
6098   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6099             (!cast<Instruction>(NAME # "v16i8")
6100                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6101   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6102             (!cast<Instruction>(NAME # "v8i16")
6103                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6104   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6105             (!cast<Instruction>(NAME # "v4i32")
6106                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6109 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6110                            bits<5> opcode, RegisterOperand regtype, string asm,
6111                            string kind, string zero, ValueType dty,
6112                            ValueType sty, SDNode OpNode>
6113   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6114       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6115       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6116       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6117     Sched<[WriteV]> {
6118   bits<5> Rd;
6119   bits<5> Rn;
6120   let Inst{31}    = 0;
6121   let Inst{30}    = Q;
6122   let Inst{29}    = U;
6123   let Inst{28-24} = 0b01110;
6124   let Inst{23-22} = size;
6125   let Inst{21} = 0b1;
6126   let Inst{20-19} = size2;
6127   let Inst{18-17} = 0b00;
6128   let Inst{16-12} = opcode;
6129   let Inst{11-10} = 0b10;
6130   let Inst{9-5}   = Rn;
6131   let Inst{4-0}   = Rd;
6134 // Comparisons support all element sizes, except 1xD.
6135 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6136                             SDNode OpNode> {
6137   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6138                                      asm, ".8b", "0",
6139                                      v8i8, v8i8, OpNode>;
6140   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6141                                      asm, ".16b", "0",
6142                                      v16i8, v16i8, OpNode>;
6143   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6144                                      asm, ".4h", "0",
6145                                      v4i16, v4i16, OpNode>;
6146   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6147                                      asm, ".8h", "0",
6148                                      v8i16, v8i16, OpNode>;
6149   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6150                                      asm, ".2s", "0",
6151                                      v2i32, v2i32, OpNode>;
6152   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6153                                      asm, ".4s", "0",
6154                                      v4i32, v4i32, OpNode>;
6155   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6156                                      asm, ".2d", "0",
6157                                      v2i64, v2i64, OpNode>;
6160 // FP Comparisons support only S and D element sizes (and H for v8.2a).
6161 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6162                               string asm, SDNode OpNode> {
6164   let Predicates = [HasNEON, HasFullFP16] in {
6165   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6166                                      asm, ".4h", "0.0",
6167                                      v4i16, v4f16, OpNode>;
6168   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6169                                      asm, ".8h", "0.0",
6170                                      v8i16, v8f16, OpNode>;
6171   } // Predicates = [HasNEON, HasFullFP16]
6172   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6173                                      asm, ".2s", "0.0",
6174                                      v2i32, v2f32, OpNode>;
6175   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6176                                      asm, ".4s", "0.0",
6177                                      v4i32, v4f32, OpNode>;
6178   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6179                                      asm, ".2d", "0.0",
6180                                      v2i64, v2f64, OpNode>;
6182   let Predicates = [HasNEON, HasFullFP16] in {
6183   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6184                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6185   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6186                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6187   }
6188   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6189                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6190   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6191                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6192   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6193                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6194   let Predicates = [HasNEON, HasFullFP16] in {
6195   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6196                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6197   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6198                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6199   }
6200   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6201                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6202   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6203                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6204   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6205                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6208 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6209 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6210                              RegisterOperand outtype, RegisterOperand intype,
6211                              string asm, string VdTy, string VnTy,
6212                              list<dag> pattern>
6213   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6214       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6215     Sched<[WriteV]> {
6216   bits<5> Rd;
6217   bits<5> Rn;
6218   let Inst{31}    = 0;
6219   let Inst{30}    = Q;
6220   let Inst{29}    = U;
6221   let Inst{28-24} = 0b01110;
6222   let Inst{23-22} = size;
6223   let Inst{21-17} = 0b10000;
6224   let Inst{16-12} = opcode;
6225   let Inst{11-10} = 0b10;
6226   let Inst{9-5}   = Rn;
6227   let Inst{4-0}   = Rd;
6230 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6231                              RegisterOperand outtype, RegisterOperand intype,
6232                              string asm, string VdTy, string VnTy,
6233                              list<dag> pattern>
6234   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6235       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6236     Sched<[WriteV]> {
6237   bits<5> Rd;
6238   bits<5> Rn;
6239   let Inst{31}    = 0;
6240   let Inst{30}    = Q;
6241   let Inst{29}    = U;
6242   let Inst{28-24} = 0b01110;
6243   let Inst{23-22} = size;
6244   let Inst{21-17} = 0b10000;
6245   let Inst{16-12} = opcode;
6246   let Inst{11-10} = 0b10;
6247   let Inst{9-5}   = Rn;
6248   let Inst{4-0}   = Rd;
6251 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6252   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6253                                     asm, ".4s", ".4h", []>;
6254   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6255                                     asm#"2", ".4s", ".8h", []>;
6256   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6257                                     asm, ".2d", ".2s", []>;
6258   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6259                                     asm#"2", ".2d", ".4s", []>;
6262 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6263   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6264                                     asm, ".4h", ".4s", []>;
6265   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6266                                     asm#"2", ".8h", ".4s", []>;
6267   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6268                                     asm, ".2s", ".2d", []>;
6269   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6270                                     asm#"2", ".4s", ".2d", []>;
6273 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6274                                      Intrinsic OpNode> {
6275   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6276                                      asm, ".2s", ".2d",
6277                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6278   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6279                                     asm#"2", ".4s", ".2d", []>;
6281   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6282             (!cast<Instruction>(NAME # "v4f32")
6283                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6286 //----------------------------------------------------------------------------
6287 // AdvSIMD three register different-size vector instructions.
6288 //----------------------------------------------------------------------------
6290 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6291 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6292                       RegisterOperand outtype, RegisterOperand intype1,
6293                       RegisterOperand intype2, string asm,
6294                       string outkind, string inkind1, string inkind2,
6295                       list<dag> pattern>
6296   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6297       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6298       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6299     Sched<[WriteV]> {
6300   bits<5> Rd;
6301   bits<5> Rn;
6302   bits<5> Rm;
6303   let Inst{31}    = 0;
6304   let Inst{30}    = size{0};
6305   let Inst{29}    = U;
6306   let Inst{28-24} = 0b01110;
6307   let Inst{23-22} = size{2-1};
6308   let Inst{21}    = 1;
6309   let Inst{20-16} = Rm;
6310   let Inst{15-12} = opcode;
6311   let Inst{11-10} = 0b00;
6312   let Inst{9-5}   = Rn;
6313   let Inst{4-0}   = Rd;
6316 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6317 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6318                       RegisterOperand outtype, RegisterOperand intype1,
6319                       RegisterOperand intype2, string asm,
6320                       string outkind, string inkind1, string inkind2,
6321                       list<dag> pattern>
6322   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6323       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6324       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6325     Sched<[WriteV]> {
6326   bits<5> Rd;
6327   bits<5> Rn;
6328   bits<5> Rm;
6329   let Inst{31}    = 0;
6330   let Inst{30}    = size{0};
6331   let Inst{29}    = U;
6332   let Inst{28-24} = 0b01110;
6333   let Inst{23-22} = size{2-1};
6334   let Inst{21}    = 1;
6335   let Inst{20-16} = Rm;
6336   let Inst{15-12} = opcode;
6337   let Inst{11-10} = 0b00;
6338   let Inst{9-5}   = Rn;
6339   let Inst{4-0}   = Rd;
6342 // FIXME: TableGen doesn't know how to deal with expanded types that also
6343 //        change the element count (in this case, placing the results in
6344 //        the high elements of the result register rather than the low
6345 //        elements). Until that's fixed, we can't code-gen those.
6346 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6347                                     Intrinsic IntOp> {
6348   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6349                                                   V64, V128, V128,
6350                                                   asm, ".8b", ".8h", ".8h",
6351      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6352   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6353                                                   V128, V128, V128,
6354                                                   asm#"2", ".16b", ".8h", ".8h",
6355      []>;
6356   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6357                                                   V64, V128, V128,
6358                                                   asm, ".4h", ".4s", ".4s",
6359      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6360   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6361                                                   V128, V128, V128,
6362                                                   asm#"2", ".8h", ".4s", ".4s",
6363      []>;
6364   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6365                                                   V64, V128, V128,
6366                                                   asm, ".2s", ".2d", ".2d",
6367      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6368   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6369                                                   V128, V128, V128,
6370                                                   asm#"2", ".4s", ".2d", ".2d",
6371      []>;
6374   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6375   // a version attached to an instruction.
6376   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6377                                                    (v8i16 V128:$Rm))),
6378             (!cast<Instruction>(NAME # "v8i16_v16i8")
6379                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6380                 V128:$Rn, V128:$Rm)>;
6381   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6382                                                     (v4i32 V128:$Rm))),
6383             (!cast<Instruction>(NAME # "v4i32_v8i16")
6384                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6385                 V128:$Rn, V128:$Rm)>;
6386   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6387                                                     (v2i64 V128:$Rm))),
6388             (!cast<Instruction>(NAME # "v2i64_v4i32")
6389                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6390                 V128:$Rn, V128:$Rm)>;
6393 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6394                                       Intrinsic IntOp> {
6395   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6396                                             V128, V64, V64,
6397                                             asm, ".8h", ".8b", ".8b",
6398       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6399   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6400                                             V128, V128, V128,
6401                                             asm#"2", ".8h", ".16b", ".16b", []>;
6402   let Predicates = [HasAES] in {
6403     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6404                                               V128, V64, V64,
6405                                               asm, ".1q", ".1d", ".1d", []>;
6406     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6407                                               V128, V128, V128,
6408                                               asm#"2", ".1q", ".2d", ".2d", []>;
6409   }
6411   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6412                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
6413       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6416 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6417                                  SDPatternOperator OpNode> {
6418   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6419                                                   V128, V64, V64,
6420                                                   asm, ".4s", ".4h", ".4h",
6421       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6422   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6423                                                   V128, V128, V128,
6424                                                   asm#"2", ".4s", ".8h", ".8h",
6425       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6426                                       (extract_high_v8i16 V128:$Rm)))]>;
6427   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6428                                                   V128, V64, V64,
6429                                                   asm, ".2d", ".2s", ".2s",
6430       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6431   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6432                                                   V128, V128, V128,
6433                                                   asm#"2", ".2d", ".4s", ".4s",
6434       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6435                                       (extract_high_v4i32 V128:$Rm)))]>;
6438 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6439                                   SDPatternOperator OpNode = null_frag> {
6440   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6441                                                   V128, V64, V64,
6442                                                   asm, ".8h", ".8b", ".8b",
6443       [(set (v8i16 V128:$Rd),
6444             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6445   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6446                                                  V128, V128, V128,
6447                                                  asm#"2", ".8h", ".16b", ".16b",
6448       [(set (v8i16 V128:$Rd),
6449             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6450                                 (extract_high_v16i8 V128:$Rm)))))]>;
6451   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6452                                                   V128, V64, V64,
6453                                                   asm, ".4s", ".4h", ".4h",
6454       [(set (v4i32 V128:$Rd),
6455             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6456   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6457                                                   V128, V128, V128,
6458                                                   asm#"2", ".4s", ".8h", ".8h",
6459       [(set (v4i32 V128:$Rd),
6460             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6461                                   (extract_high_v8i16 V128:$Rm)))))]>;
6462   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6463                                                   V128, V64, V64,
6464                                                   asm, ".2d", ".2s", ".2s",
6465       [(set (v2i64 V128:$Rd),
6466             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6467   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6468                                                   V128, V128, V128,
6469                                                   asm#"2", ".2d", ".4s", ".4s",
6470       [(set (v2i64 V128:$Rd),
6471             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6472                                  (extract_high_v4i32 V128:$Rm)))))]>;
6475 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6476                                           string asm,
6477                                           SDPatternOperator OpNode> {
6478   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6479                                                   V128, V64, V64,
6480                                                   asm, ".8h", ".8b", ".8b",
6481     [(set (v8i16 V128:$dst),
6482           (add (v8i16 V128:$Rd),
6483                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6484   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6485                                                  V128, V128, V128,
6486                                                  asm#"2", ".8h", ".16b", ".16b",
6487     [(set (v8i16 V128:$dst),
6488           (add (v8i16 V128:$Rd),
6489                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6490                                    (extract_high_v16i8 V128:$Rm))))))]>;
6491   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6492                                                   V128, V64, V64,
6493                                                   asm, ".4s", ".4h", ".4h",
6494     [(set (v4i32 V128:$dst),
6495           (add (v4i32 V128:$Rd),
6496                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6497   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6498                                                   V128, V128, V128,
6499                                                   asm#"2", ".4s", ".8h", ".8h",
6500     [(set (v4i32 V128:$dst),
6501           (add (v4i32 V128:$Rd),
6502                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6503                                     (extract_high_v8i16 V128:$Rm))))))]>;
6504   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6505                                                   V128, V64, V64,
6506                                                   asm, ".2d", ".2s", ".2s",
6507     [(set (v2i64 V128:$dst),
6508           (add (v2i64 V128:$Rd),
6509                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6510   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6511                                                   V128, V128, V128,
6512                                                   asm#"2", ".2d", ".4s", ".4s",
6513     [(set (v2i64 V128:$dst),
6514           (add (v2i64 V128:$Rd),
6515                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6516                                     (extract_high_v4i32 V128:$Rm))))))]>;
6519 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6520                                   SDPatternOperator OpNode = null_frag> {
6521   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6522                                                   V128, V64, V64,
6523                                                   asm, ".8h", ".8b", ".8b",
6524       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6525   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6526                                                  V128, V128, V128,
6527                                                  asm#"2", ".8h", ".16b", ".16b",
6528       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6529                                       (extract_high_v16i8 V128:$Rm)))]>;
6530   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6531                                                   V128, V64, V64,
6532                                                   asm, ".4s", ".4h", ".4h",
6533       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6534   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6535                                                   V128, V128, V128,
6536                                                   asm#"2", ".4s", ".8h", ".8h",
6537       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6538                                       (extract_high_v8i16 V128:$Rm)))]>;
6539   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6540                                                   V128, V64, V64,
6541                                                   asm, ".2d", ".2s", ".2s",
6542       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6543   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6544                                                   V128, V128, V128,
6545                                                   asm#"2", ".2d", ".4s", ".4s",
6546       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6547                                       (extract_high_v4i32 V128:$Rm)))]>;
6550 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6551                                       string asm,
6552                                       SDPatternOperator OpNode> {
6553   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6554                                                   V128, V64, V64,
6555                                                   asm, ".8h", ".8b", ".8b",
6556     [(set (v8i16 V128:$dst),
6557           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6558   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6559                                                  V128, V128, V128,
6560                                                  asm#"2", ".8h", ".16b", ".16b",
6561     [(set (v8i16 V128:$dst),
6562           (OpNode (v8i16 V128:$Rd),
6563                   (extract_high_v16i8 V128:$Rn),
6564                   (extract_high_v16i8 V128:$Rm)))]>;
6565   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6566                                                   V128, V64, V64,
6567                                                   asm, ".4s", ".4h", ".4h",
6568     [(set (v4i32 V128:$dst),
6569           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6570   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6571                                                   V128, V128, V128,
6572                                                   asm#"2", ".4s", ".8h", ".8h",
6573     [(set (v4i32 V128:$dst),
6574           (OpNode (v4i32 V128:$Rd),
6575                   (extract_high_v8i16 V128:$Rn),
6576                   (extract_high_v8i16 V128:$Rm)))]>;
6577   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6578                                                   V128, V64, V64,
6579                                                   asm, ".2d", ".2s", ".2s",
6580     [(set (v2i64 V128:$dst),
6581           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6582   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6583                                                   V128, V128, V128,
6584                                                   asm#"2", ".2d", ".4s", ".4s",
6585     [(set (v2i64 V128:$dst),
6586           (OpNode (v2i64 V128:$Rd),
6587                   (extract_high_v4i32 V128:$Rn),
6588                   (extract_high_v4i32 V128:$Rm)))]>;
6591 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6592                                            SDPatternOperator Accum> {
6593   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6594                                                   V128, V64, V64,
6595                                                   asm, ".4s", ".4h", ".4h",
6596     [(set (v4i32 V128:$dst),
6597           (Accum (v4i32 V128:$Rd),
6598                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6599                                                 (v4i16 V64:$Rm)))))]>;
6600   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6601                                                   V128, V128, V128,
6602                                                   asm#"2", ".4s", ".8h", ".8h",
6603     [(set (v4i32 V128:$dst),
6604           (Accum (v4i32 V128:$Rd),
6605                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6606                                             (extract_high_v8i16 V128:$Rm)))))]>;
6607   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6608                                                   V128, V64, V64,
6609                                                   asm, ".2d", ".2s", ".2s",
6610     [(set (v2i64 V128:$dst),
6611           (Accum (v2i64 V128:$Rd),
6612                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6613                                                 (v2i32 V64:$Rm)))))]>;
6614   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6615                                                   V128, V128, V128,
6616                                                   asm#"2", ".2d", ".4s", ".4s",
6617     [(set (v2i64 V128:$dst),
6618           (Accum (v2i64 V128:$Rd),
6619                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6620                                             (extract_high_v4i32 V128:$Rm)))))]>;
6623 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6624                                   SDPatternOperator OpNode> {
6625   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6626                                                   V128, V128, V64,
6627                                                   asm, ".8h", ".8h", ".8b",
6628        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6629   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6630                                                   V128, V128, V128,
6631                                                   asm#"2", ".8h", ".8h", ".16b",
6632        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6633                                        (extract_high_v16i8 V128:$Rm)))]>;
6634   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6635                                                   V128, V128, V64,
6636                                                   asm, ".4s", ".4s", ".4h",
6637        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6638   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6639                                                   V128, V128, V128,
6640                                                   asm#"2", ".4s", ".4s", ".8h",
6641        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6642                                        (extract_high_v8i16 V128:$Rm)))]>;
6643   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6644                                                   V128, V128, V64,
6645                                                   asm, ".2d", ".2d", ".2s",
6646        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6647   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6648                                                   V128, V128, V128,
6649                                                   asm#"2", ".2d", ".2d", ".4s",
6650        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6651                                        (extract_high_v4i32 V128:$Rm)))]>;
6654 //----------------------------------------------------------------------------
6655 // AdvSIMD bitwise extract from vector
6656 //----------------------------------------------------------------------------
6658 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6659                              string asm, string kind>
6660   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6661       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6662       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6663       [(set (vty regtype:$Rd),
6664             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6665     Sched<[WriteV]> {
6666   bits<5> Rd;
6667   bits<5> Rn;
6668   bits<5> Rm;
6669   bits<4> imm;
6670   let Inst{31}    = 0;
6671   let Inst{30}    = size;
6672   let Inst{29-21} = 0b101110000;
6673   let Inst{20-16} = Rm;
6674   let Inst{15}    = 0;
6675   let Inst{14-11} = imm;
6676   let Inst{10}    = 0;
6677   let Inst{9-5}   = Rn;
6678   let Inst{4-0}   = Rd;
6682 multiclass SIMDBitwiseExtract<string asm> {
6683   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6684     let imm{3} = 0;
6685   }
6686   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6689 //----------------------------------------------------------------------------
6690 // AdvSIMD zip vector
6691 //----------------------------------------------------------------------------
6693 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6694                         string asm, string kind, SDNode OpNode, ValueType valty>
6695   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6696       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6697       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6698       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6699     Sched<[WriteV]> {
6700   bits<5> Rd;
6701   bits<5> Rn;
6702   bits<5> Rm;
6703   let Inst{31}    = 0;
6704   let Inst{30}    = size{0};
6705   let Inst{29-24} = 0b001110;
6706   let Inst{23-22} = size{2-1};
6707   let Inst{21}    = 0;
6708   let Inst{20-16} = Rm;
6709   let Inst{15}    = 0;
6710   let Inst{14-12} = opc;
6711   let Inst{11-10} = 0b10;
6712   let Inst{9-5}   = Rn;
6713   let Inst{4-0}   = Rd;
6716 multiclass SIMDZipVector<bits<3>opc, string asm,
6717                          SDNode OpNode> {
6718   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6719       asm, ".8b", OpNode, v8i8>;
6720   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6721       asm, ".16b", OpNode, v16i8>;
6722   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6723       asm, ".4h", OpNode, v4i16>;
6724   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6725       asm, ".8h", OpNode, v8i16>;
6726   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6727       asm, ".2s", OpNode, v2i32>;
6728   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6729       asm, ".4s", OpNode, v4i32>;
6730   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6731       asm, ".2d", OpNode, v2i64>;
6733   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6734         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6735   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6736         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6737   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6738         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6739   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6740         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6741   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6742         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6745 //----------------------------------------------------------------------------
6746 // AdvSIMD three register scalar instructions
6747 //----------------------------------------------------------------------------
6749 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6750 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6751                         RegisterClass regtype, string asm,
6752                         list<dag> pattern>
6753   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6754       "\t$Rd, $Rn, $Rm", "", pattern>,
6755     Sched<[WriteV]> {
6756   bits<5> Rd;
6757   bits<5> Rn;
6758   bits<5> Rm;
6759   let Inst{31-30} = 0b01;
6760   let Inst{29}    = U;
6761   let Inst{28-24} = 0b11110;
6762   let Inst{23-21} = size;
6763   let Inst{20-16} = Rm;
6764   let Inst{15-11} = opcode;
6765   let Inst{10}    = 1;
6766   let Inst{9-5}   = Rn;
6767   let Inst{4-0}   = Rd;
6770 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6771 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6772                         dag oops, dag iops, string asm,
6773             list<dag> pattern>
6774   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6775     Sched<[WriteV]> {
6776   bits<5> Rd;
6777   bits<5> Rn;
6778   bits<5> Rm;
6779   let Inst{31-30} = 0b01;
6780   let Inst{29}    = U;
6781   let Inst{28-24} = 0b11110;
6782   let Inst{23-22} = size;
6783   let Inst{21}    = R;
6784   let Inst{20-16} = Rm;
6785   let Inst{15-11} = opcode;
6786   let Inst{10}    = 1;
6787   let Inst{9-5}   = Rn;
6788   let Inst{4-0}   = Rd;
6791 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6792                             SDPatternOperator OpNode> {
6793   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6794     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6797 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6798                                SDPatternOperator OpNode> {
6799   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6800     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6801   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6802   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6803   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6805   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6806             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6807   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6808             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6811 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6812                              SDPatternOperator OpNode> {
6813   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6814                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6815   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6818 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6819                                  SDPatternOperator OpNode = null_frag> {
6820   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6821                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6822                                      asm, []>;
6823   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6824                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6825                                      asm, []>;
6828 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6829                              SDPatternOperator OpNode = null_frag> {
6830   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6831     def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6832       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6833     def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6834       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6835     let Predicates = [HasNEON, HasFullFP16] in {
6836     def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6837       [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6838     } // Predicates = [HasNEON, HasFullFP16]
6839   }
6841   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6842             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6845 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6846                                 SDPatternOperator OpNode = null_frag> {
6847   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6848     def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6849       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6850     def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6851       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6852     let Predicates = [HasNEON, HasFullFP16] in {
6853     def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6854       []>;
6855     } // Predicates = [HasNEON, HasFullFP16]
6856   }
6858   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6859             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6862 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6863               dag oops, dag iops, string asm, string cstr, list<dag> pat>
6864   : I<oops, iops, asm,
6865       "\t$Rd, $Rn, $Rm", cstr, pat>,
6866     Sched<[WriteV]> {
6867   bits<5> Rd;
6868   bits<5> Rn;
6869   bits<5> Rm;
6870   let Inst{31-30} = 0b01;
6871   let Inst{29}    = U;
6872   let Inst{28-24} = 0b11110;
6873   let Inst{23-22} = size;
6874   let Inst{21}    = 1;
6875   let Inst{20-16} = Rm;
6876   let Inst{15-11} = opcode;
6877   let Inst{10}    = 0;
6878   let Inst{9-5}   = Rn;
6879   let Inst{4-0}   = Rd;
6882 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6883 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6884                                   SDPatternOperator OpNode = null_frag> {
6885   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6886                                       (outs FPR32:$Rd),
6887                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6888   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6889                                       (outs FPR64:$Rd),
6890                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6891             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6894 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6895 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6896                                   SDPatternOperator OpNode = null_frag> {
6897   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6898                                       (outs FPR32:$dst),
6899                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6900                                       asm, "$Rd = $dst", []>;
6901   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6902                                       (outs FPR64:$dst),
6903                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6904                                       asm, "$Rd = $dst",
6905             [(set (i64 FPR64:$dst),
6906                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6909 //----------------------------------------------------------------------------
6910 // AdvSIMD two register scalar instructions
6911 //----------------------------------------------------------------------------
6913 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6914 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6915                         RegisterClass regtype, RegisterClass regtype2,
6916                         string asm, list<dag> pat>
6917   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6918       "\t$Rd, $Rn", "", pat>,
6919     Sched<[WriteV]> {
6920   bits<5> Rd;
6921   bits<5> Rn;
6922   let Inst{31-30} = 0b01;
6923   let Inst{29}    = U;
6924   let Inst{28-24} = 0b11110;
6925   let Inst{23-22} = size;
6926   let Inst{21} = 0b1;
6927   let Inst{20-19} = size2;
6928   let Inst{18-17} = 0b00;
6929   let Inst{16-12} = opcode;
6930   let Inst{11-10} = 0b10;
6931   let Inst{9-5}   = Rn;
6932   let Inst{4-0}   = Rd;
6935 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6936 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6937                         RegisterClass regtype, RegisterClass regtype2,
6938                         string asm, list<dag> pat>
6939   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6940       "\t$Rd, $Rn", "$Rd = $dst", pat>,
6941     Sched<[WriteV]> {
6942   bits<5> Rd;
6943   bits<5> Rn;
6944   let Inst{31-30} = 0b01;
6945   let Inst{29}    = U;
6946   let Inst{28-24} = 0b11110;
6947   let Inst{23-22} = size;
6948   let Inst{21-17} = 0b10000;
6949   let Inst{16-12} = opcode;
6950   let Inst{11-10} = 0b10;
6951   let Inst{9-5}   = Rn;
6952   let Inst{4-0}   = Rd;
6956 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6957 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6958                         RegisterClass regtype, string asm, string zero>
6959   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6960       "\t$Rd, $Rn, #" # zero, "", []>,
6961     Sched<[WriteV]> {
6962   bits<5> Rd;
6963   bits<5> Rn;
6964   let Inst{31-30} = 0b01;
6965   let Inst{29}    = U;
6966   let Inst{28-24} = 0b11110;
6967   let Inst{23-22} = size;
6968   let Inst{21} = 0b1;
6969   let Inst{20-19} = size2;
6970   let Inst{18-17} = 0b00;
6971   let Inst{16-12} = opcode;
6972   let Inst{11-10} = 0b10;
6973   let Inst{9-5}   = Rn;
6974   let Inst{4-0}   = Rd;
6977 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6978   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6979      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6980     Sched<[WriteV]> {
6981   bits<5> Rd;
6982   bits<5> Rn;
6983   let Inst{31-17} = 0b011111100110000;
6984   let Inst{16-12} = opcode;
6985   let Inst{11-10} = 0b10;
6986   let Inst{9-5}   = Rn;
6987   let Inst{4-0}   = Rd;
6990 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6991                              SDPatternOperator OpNode> {
6992   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6994   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6995             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6998 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6999                               SDPatternOperator OpNode> {
7000   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7001   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7002   let Predicates = [HasNEON, HasFullFP16] in {
7003   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7004   }
7006   def : InstAlias<asm # "\t$Rd, $Rn, #0",
7007                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7008   def : InstAlias<asm # "\t$Rd, $Rn, #0",
7009                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7010   let Predicates = [HasNEON, HasFullFP16] in {
7011   def : InstAlias<asm # "\t$Rd, $Rn, #0",
7012                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7013   }
7015   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7016             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7019 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7020                           SDPatternOperator OpNode = null_frag> {
7021   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7022     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7024   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7025             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7028 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
7029   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7030   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7031   let Predicates = [HasNEON, HasFullFP16] in {
7032   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7033   }
7036 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7037                               SDPatternOperator OpNode> {
7038   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7039                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7040   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7041                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7042   let Predicates = [HasNEON, HasFullFP16] in {
7043   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7044                                 [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7045   }
7048 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7049                              SDPatternOperator OpNode = null_frag> {
7050   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7051     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7052            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7053     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7054            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7055     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7056     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7057   }
7059   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7060             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7063 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7064                                  Intrinsic OpNode> {
7065   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7066     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7067         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7068     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7069         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7070     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7071     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7072   }
7074   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7075             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7080 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7081 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7082                                  SDPatternOperator OpNode = null_frag> {
7083   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7084         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7085   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7086   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7089 //----------------------------------------------------------------------------
7090 // AdvSIMD scalar pairwise instructions
7091 //----------------------------------------------------------------------------
7093 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7094 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7095                         RegisterOperand regtype, RegisterOperand vectype,
7096                         string asm, string kind>
7097   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7098       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7099     Sched<[WriteV]> {
7100   bits<5> Rd;
7101   bits<5> Rn;
7102   let Inst{31-30} = 0b01;
7103   let Inst{29}    = U;
7104   let Inst{28-24} = 0b11110;
7105   let Inst{23-22} = size;
7106   let Inst{21-17} = 0b11000;
7107   let Inst{16-12} = opcode;
7108   let Inst{11-10} = 0b10;
7109   let Inst{9-5}   = Rn;
7110   let Inst{4-0}   = Rd;
7113 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7114   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7115                                       asm, ".2d">;
7118 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7119   let Predicates = [HasNEON, HasFullFP16] in {
7120   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7121                                       asm, ".2h">;
7122   }
7123   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7124                                       asm, ".2s">;
7125   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7126                                       asm, ".2d">;
7129 //----------------------------------------------------------------------------
7130 // AdvSIMD across lanes instructions
7131 //----------------------------------------------------------------------------
7133 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7134 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7135                           RegisterClass regtype, RegisterOperand vectype,
7136                           string asm, string kind, list<dag> pattern>
7137   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7138       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7139     Sched<[WriteV]> {
7140   bits<5> Rd;
7141   bits<5> Rn;
7142   let Inst{31}    = 0;
7143   let Inst{30}    = Q;
7144   let Inst{29}    = U;
7145   let Inst{28-24} = 0b01110;
7146   let Inst{23-22} = size;
7147   let Inst{21-17} = 0b11000;
7148   let Inst{16-12} = opcode;
7149   let Inst{11-10} = 0b10;
7150   let Inst{9-5}   = Rn;
7151   let Inst{4-0}   = Rd;
7154 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7155                               string asm> {
7156   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7157                                    asm, ".8b", []>;
7158   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7159                                    asm, ".16b", []>;
7160   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7161                                    asm, ".4h", []>;
7162   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7163                                    asm, ".8h", []>;
7164   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7165                                    asm, ".4s", []>;
7168 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7169   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7170                                    asm, ".8b", []>;
7171   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7172                                    asm, ".16b", []>;
7173   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7174                                    asm, ".4h", []>;
7175   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7176                                    asm, ".8h", []>;
7177   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7178                                    asm, ".4s", []>;
7181 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7182                             Intrinsic intOp> {
7183   let Predicates = [HasNEON, HasFullFP16] in {
7184   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7185                                    asm, ".4h",
7186         [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7187   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7188                                    asm, ".8h",
7189         [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7190   } // Predicates = [HasNEON, HasFullFP16]
7191   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7192                                    asm, ".4s",
7193         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7196 //----------------------------------------------------------------------------
7197 // AdvSIMD INS/DUP instructions
7198 //----------------------------------------------------------------------------
7200 // FIXME: There has got to be a better way to factor these. ugh.
7202 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7203                      string operands, string constraints, list<dag> pattern>
7204   : I<outs, ins, asm, operands, constraints, pattern>,
7205     Sched<[WriteV]> {
7206   bits<5> Rd;
7207   bits<5> Rn;
7208   let Inst{31} = 0;
7209   let Inst{30} = Q;
7210   let Inst{29} = op;
7211   let Inst{28-21} = 0b01110000;
7212   let Inst{15} = 0;
7213   let Inst{10} = 1;
7214   let Inst{9-5} = Rn;
7215   let Inst{4-0} = Rd;
7218 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7219                       RegisterOperand vecreg, RegisterClass regtype>
7220   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7221                    "{\t$Rd" # size # ", $Rn" #
7222                    "|" # size # "\t$Rd, $Rn}", "",
7223                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7224   let Inst{20-16} = imm5;
7225   let Inst{14-11} = 0b0001;
7228 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7229                          ValueType vectype, ValueType insreg,
7230                          RegisterOperand vecreg, Operand idxtype,
7231                          ValueType elttype, SDNode OpNode>
7232   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7233                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7234                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7235                  [(set (vectype vecreg:$Rd),
7236                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7237   let Inst{14-11} = 0b0000;
7240 class SIMDDup64FromElement
7241   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7242                        VectorIndexD, i64, AArch64duplane64> {
7243   bits<1> idx;
7244   let Inst{20} = idx;
7245   let Inst{19-16} = 0b1000;
7248 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7249                            RegisterOperand vecreg>
7250   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7251                        VectorIndexS, i64, AArch64duplane32> {
7252   bits<2> idx;
7253   let Inst{20-19} = idx;
7254   let Inst{18-16} = 0b100;
7257 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7258                            RegisterOperand vecreg>
7259   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7260                        VectorIndexH, i64, AArch64duplane16> {
7261   bits<3> idx;
7262   let Inst{20-18} = idx;
7263   let Inst{17-16} = 0b10;
7266 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7267                           RegisterOperand vecreg>
7268   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7269                        VectorIndexB, i64, AArch64duplane8> {
7270   bits<4> idx;
7271   let Inst{20-17} = idx;
7272   let Inst{16} = 1;
7275 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7276                   Operand idxtype, string asm, list<dag> pattern>
7277   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7278                    "{\t$Rd, $Rn" # size # "$idx" #
7279                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7280   let Inst{14-11} = imm4;
7283 class SIMDSMov<bit Q, string size, RegisterClass regtype,
7284                Operand idxtype>
7285   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7286 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7287                Operand idxtype>
7288   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7289       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7291 class SIMDMovAlias<string asm, string size, Instruction inst,
7292                    RegisterClass regtype, Operand idxtype>
7293     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7294                     "|" # size # "\t$dst, $src$idx}",
7295                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7297 multiclass SMov {
7298   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7299     bits<4> idx;
7300     let Inst{20-17} = idx;
7301     let Inst{16} = 1;
7302   }
7303   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7304     bits<4> idx;
7305     let Inst{20-17} = idx;
7306     let Inst{16} = 1;
7307   }
7308   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7309     bits<3> idx;
7310     let Inst{20-18} = idx;
7311     let Inst{17-16} = 0b10;
7312   }
7313   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7314     bits<3> idx;
7315     let Inst{20-18} = idx;
7316     let Inst{17-16} = 0b10;
7317   }
7318   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7319     bits<2> idx;
7320     let Inst{20-19} = idx;
7321     let Inst{18-16} = 0b100;
7322   }
7325 multiclass UMov {
7326   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7327     bits<4> idx;
7328     let Inst{20-17} = idx;
7329     let Inst{16} = 1;
7330   }
7331   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7332     bits<3> idx;
7333     let Inst{20-18} = idx;
7334     let Inst{17-16} = 0b10;
7335   }
7336   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7337     bits<2> idx;
7338     let Inst{20-19} = idx;
7339     let Inst{18-16} = 0b100;
7340   }
7341   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7342     bits<1> idx;
7343     let Inst{20} = idx;
7344     let Inst{19-16} = 0b1000;
7345   }
7346   def : SIMDMovAlias<"mov", ".s",
7347                      !cast<Instruction>(NAME#"vi32"),
7348                      GPR32, VectorIndexS>;
7349   def : SIMDMovAlias<"mov", ".d",
7350                      !cast<Instruction>(NAME#"vi64"),
7351                      GPR64, VectorIndexD>;
7354 class SIMDInsFromMain<string size, ValueType vectype,
7355                       RegisterClass regtype, Operand idxtype>
7356   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7357                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7358                    "{\t$Rd" # size # "$idx, $Rn" #
7359                    "|" # size # "\t$Rd$idx, $Rn}",
7360                    "$Rd = $dst",
7361             [(set V128:$dst,
7362               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7363   let Inst{14-11} = 0b0011;
7366 class SIMDInsFromElement<string size, ValueType vectype,
7367                          ValueType elttype, Operand idxtype>
7368   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7369                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7370                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7371                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
7372                    "$Rd = $dst",
7373          [(set V128:$dst,
7374                (vector_insert
7375                  (vectype V128:$Rd),
7376                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7377                  idxtype:$idx))]>;
7379 class SIMDInsMainMovAlias<string size, Instruction inst,
7380                           RegisterClass regtype, Operand idxtype>
7381     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7382                         "|" # size #"\t$dst$idx, $src}",
7383                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7384 class SIMDInsElementMovAlias<string size, Instruction inst,
7385                              Operand idxtype>
7386     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7387                       # "|" # size #"\t$dst$idx, $src$idx2}",
7388                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7391 multiclass SIMDIns {
7392   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7393     bits<4> idx;
7394     let Inst{20-17} = idx;
7395     let Inst{16} = 1;
7396   }
7397   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7398     bits<3> idx;
7399     let Inst{20-18} = idx;
7400     let Inst{17-16} = 0b10;
7401   }
7402   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7403     bits<2> idx;
7404     let Inst{20-19} = idx;
7405     let Inst{18-16} = 0b100;
7406   }
7407   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7408     bits<1> idx;
7409     let Inst{20} = idx;
7410     let Inst{19-16} = 0b1000;
7411   }
7413   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7414     bits<4> idx;
7415     bits<4> idx2;
7416     let Inst{20-17} = idx;
7417     let Inst{16} = 1;
7418     let Inst{14-11} = idx2;
7419   }
7420   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7421     bits<3> idx;
7422     bits<3> idx2;
7423     let Inst{20-18} = idx;
7424     let Inst{17-16} = 0b10;
7425     let Inst{14-12} = idx2;
7426     let Inst{11} = {?};
7427   }
7428   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7429     bits<2> idx;
7430     bits<2> idx2;
7431     let Inst{20-19} = idx;
7432     let Inst{18-16} = 0b100;
7433     let Inst{14-13} = idx2;
7434     let Inst{12-11} = {?,?};
7435   }
7436   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7437     bits<1> idx;
7438     bits<1> idx2;
7439     let Inst{20} = idx;
7440     let Inst{19-16} = 0b1000;
7441     let Inst{14} = idx2;
7442     let Inst{13-11} = {?,?,?};
7443   }
7445   // For all forms of the INS instruction, the "mov" mnemonic is the
7446   // preferred alias. Why they didn't just call the instruction "mov" in
7447   // the first place is a very good question indeed...
7448   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7449                          GPR32, VectorIndexB>;
7450   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7451                          GPR32, VectorIndexH>;
7452   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7453                          GPR32, VectorIndexS>;
7454   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7455                          GPR64, VectorIndexD>;
7457   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7458                          VectorIndexB>;
7459   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7460                          VectorIndexH>;
7461   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7462                          VectorIndexS>;
7463   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7464                          VectorIndexD>;
7467 //----------------------------------------------------------------------------
7468 // AdvSIMD TBL/TBX
7469 //----------------------------------------------------------------------------
7471 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7472 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7473                           RegisterOperand listtype, string asm, string kind>
7474   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7475        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7476     Sched<[WriteV]> {
7477   bits<5> Vd;
7478   bits<5> Vn;
7479   bits<5> Vm;
7480   let Inst{31}    = 0;
7481   let Inst{30}    = Q;
7482   let Inst{29-21} = 0b001110000;
7483   let Inst{20-16} = Vm;
7484   let Inst{15}    = 0;
7485   let Inst{14-13} = len;
7486   let Inst{12}    = op;
7487   let Inst{11-10} = 0b00;
7488   let Inst{9-5}   = Vn;
7489   let Inst{4-0}   = Vd;
7492 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7493 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7494                           RegisterOperand listtype, string asm, string kind>
7495   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7496        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7497     Sched<[WriteV]> {
7498   bits<5> Vd;
7499   bits<5> Vn;
7500   bits<5> Vm;
7501   let Inst{31}    = 0;
7502   let Inst{30}    = Q;
7503   let Inst{29-21} = 0b001110000;
7504   let Inst{20-16} = Vm;
7505   let Inst{15}    = 0;
7506   let Inst{14-13} = len;
7507   let Inst{12}    = op;
7508   let Inst{11-10} = 0b00;
7509   let Inst{9-5}   = Vn;
7510   let Inst{4-0}   = Vd;
7513 class SIMDTableLookupAlias<string asm, Instruction inst,
7514                           RegisterOperand vectype, RegisterOperand listtype>
7515     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7516                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7518 multiclass SIMDTableLookup<bit op, string asm> {
7519   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7520                                       asm, ".8b">;
7521   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7522                                       asm, ".8b">;
7523   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7524                                       asm, ".8b">;
7525   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7526                                       asm, ".8b">;
7527   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7528                                       asm, ".16b">;
7529   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7530                                       asm, ".16b">;
7531   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7532                                       asm, ".16b">;
7533   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7534                                       asm, ".16b">;
7536   def : SIMDTableLookupAlias<asm # ".8b",
7537                          !cast<Instruction>(NAME#"v8i8One"),
7538                          V64, VecListOne128>;
7539   def : SIMDTableLookupAlias<asm # ".8b",
7540                          !cast<Instruction>(NAME#"v8i8Two"),
7541                          V64, VecListTwo128>;
7542   def : SIMDTableLookupAlias<asm # ".8b",
7543                          !cast<Instruction>(NAME#"v8i8Three"),
7544                          V64, VecListThree128>;
7545   def : SIMDTableLookupAlias<asm # ".8b",
7546                          !cast<Instruction>(NAME#"v8i8Four"),
7547                          V64, VecListFour128>;
7548   def : SIMDTableLookupAlias<asm # ".16b",
7549                          !cast<Instruction>(NAME#"v16i8One"),
7550                          V128, VecListOne128>;
7551   def : SIMDTableLookupAlias<asm # ".16b",
7552                          !cast<Instruction>(NAME#"v16i8Two"),
7553                          V128, VecListTwo128>;
7554   def : SIMDTableLookupAlias<asm # ".16b",
7555                          !cast<Instruction>(NAME#"v16i8Three"),
7556                          V128, VecListThree128>;
7557   def : SIMDTableLookupAlias<asm # ".16b",
7558                          !cast<Instruction>(NAME#"v16i8Four"),
7559                          V128, VecListFour128>;
7562 multiclass SIMDTableLookupTied<bit op, string asm> {
7563   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7564                                       asm, ".8b">;
7565   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7566                                       asm, ".8b">;
7567   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7568                                       asm, ".8b">;
7569   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7570                                       asm, ".8b">;
7571   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7572                                       asm, ".16b">;
7573   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7574                                       asm, ".16b">;
7575   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7576                                       asm, ".16b">;
7577   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7578                                       asm, ".16b">;
7580   def : SIMDTableLookupAlias<asm # ".8b",
7581                          !cast<Instruction>(NAME#"v8i8One"),
7582                          V64, VecListOne128>;
7583   def : SIMDTableLookupAlias<asm # ".8b",
7584                          !cast<Instruction>(NAME#"v8i8Two"),
7585                          V64, VecListTwo128>;
7586   def : SIMDTableLookupAlias<asm # ".8b",
7587                          !cast<Instruction>(NAME#"v8i8Three"),
7588                          V64, VecListThree128>;
7589   def : SIMDTableLookupAlias<asm # ".8b",
7590                          !cast<Instruction>(NAME#"v8i8Four"),
7591                          V64, VecListFour128>;
7592   def : SIMDTableLookupAlias<asm # ".16b",
7593                          !cast<Instruction>(NAME#"v16i8One"),
7594                          V128, VecListOne128>;
7595   def : SIMDTableLookupAlias<asm # ".16b",
7596                          !cast<Instruction>(NAME#"v16i8Two"),
7597                          V128, VecListTwo128>;
7598   def : SIMDTableLookupAlias<asm # ".16b",
7599                          !cast<Instruction>(NAME#"v16i8Three"),
7600                          V128, VecListThree128>;
7601   def : SIMDTableLookupAlias<asm # ".16b",
7602                          !cast<Instruction>(NAME#"v16i8Four"),
7603                          V128, VecListFour128>;
7607 //----------------------------------------------------------------------------
7608 // AdvSIMD scalar CPY
7609 //----------------------------------------------------------------------------
7610 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7611 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7612                         string kind, Operand idxtype>
7613   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7614        "{\t$dst, $src" # kind # "$idx" #
7615        "|\t$dst, $src$idx}", "", []>,
7616     Sched<[WriteV]> {
7617   bits<5> dst;
7618   bits<5> src;
7619   let Inst{31-21} = 0b01011110000;
7620   let Inst{15-10} = 0b000001;
7621   let Inst{9-5}   = src;
7622   let Inst{4-0}   = dst;
7625 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7626       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7627     : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7628                     # "|\t$dst, $src$index}",
7629                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7632 multiclass SIMDScalarCPY<string asm> {
7633   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7634     bits<4> idx;
7635     let Inst{20-17} = idx;
7636     let Inst{16} = 1;
7637   }
7638   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7639     bits<3> idx;
7640     let Inst{20-18} = idx;
7641     let Inst{17-16} = 0b10;
7642   }
7643   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7644     bits<2> idx;
7645     let Inst{20-19} = idx;
7646     let Inst{18-16} = 0b100;
7647   }
7648   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7649     bits<1> idx;
7650     let Inst{20} = idx;
7651     let Inst{19-16} = 0b1000;
7652   }
7654   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7655                                                           VectorIndexD:$idx)))),
7656             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7658   // 'DUP' mnemonic aliases.
7659   def : SIMDScalarCPYAlias<"dup", ".b",
7660                            !cast<Instruction>(NAME#"i8"),
7661                            FPR8, V128, VectorIndexB>;
7662   def : SIMDScalarCPYAlias<"dup", ".h",
7663                            !cast<Instruction>(NAME#"i16"),
7664                            FPR16, V128, VectorIndexH>;
7665   def : SIMDScalarCPYAlias<"dup", ".s",
7666                            !cast<Instruction>(NAME#"i32"),
7667                            FPR32, V128, VectorIndexS>;
7668   def : SIMDScalarCPYAlias<"dup", ".d",
7669                            !cast<Instruction>(NAME#"i64"),
7670                            FPR64, V128, VectorIndexD>;
7673 //----------------------------------------------------------------------------
7674 // AdvSIMD modified immediate instructions
7675 //----------------------------------------------------------------------------
7677 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7678                           string asm, string op_string,
7679                           string cstr, list<dag> pattern>
7680   : I<oops, iops, asm, op_string, cstr, pattern>,
7681     Sched<[WriteV]> {
7682   bits<5> Rd;
7683   bits<8> imm8;
7684   let Inst{31}    = 0;
7685   let Inst{30}    = Q;
7686   let Inst{29}    = op;
7687   let Inst{28-19} = 0b0111100000;
7688   let Inst{18-16} = imm8{7-5};
7689   let Inst{11} = op2;
7690   let Inst{10} = 1;
7691   let Inst{9-5}   = imm8{4-0};
7692   let Inst{4-0}   = Rd;
7695 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7696                                 Operand immtype, dag opt_shift_iop,
7697                                 string opt_shift, string asm, string kind,
7698                                 list<dag> pattern>
7699   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7700                         !con((ins immtype:$imm8), opt_shift_iop), asm,
7701                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
7702                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7703                         "", pattern> {
7704   let DecoderMethod = "DecodeModImmInstruction";
7707 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7708                                 Operand immtype, dag opt_shift_iop,
7709                                 string opt_shift, string asm, string kind,
7710                                 list<dag> pattern>
7711   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7712                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7713                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7714                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7715                         "$Rd = $dst", pattern> {
7716   let DecoderMethod = "DecodeModImmTiedInstruction";
7719 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7720                                      RegisterOperand vectype, string asm,
7721                                      string kind, list<dag> pattern>
7722   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7723                               (ins logical_vec_shift:$shift),
7724                               "$shift", asm, kind, pattern> {
7725   bits<2> shift;
7726   let Inst{15}    = b15_b12{1};
7727   let Inst{14-13} = shift;
7728   let Inst{12}    = b15_b12{0};
7731 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7732                                      RegisterOperand vectype, string asm,
7733                                      string kind, list<dag> pattern>
7734   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7735                               (ins logical_vec_shift:$shift),
7736                               "$shift", asm, kind, pattern> {
7737   bits<2> shift;
7738   let Inst{15}    = b15_b12{1};
7739   let Inst{14-13} = shift;
7740   let Inst{12}    = b15_b12{0};
7744 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7745                                          RegisterOperand vectype, string asm,
7746                                          string kind, list<dag> pattern>
7747   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7748                               (ins logical_vec_hw_shift:$shift),
7749                               "$shift", asm, kind, pattern> {
7750   bits<2> shift;
7751   let Inst{15} = b15_b12{1};
7752   let Inst{14} = 0;
7753   let Inst{13} = shift{0};
7754   let Inst{12} = b15_b12{0};
7757 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7758                                          RegisterOperand vectype, string asm,
7759                                          string kind, list<dag> pattern>
7760   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7761                               (ins logical_vec_hw_shift:$shift),
7762                               "$shift", asm, kind, pattern> {
7763   bits<2> shift;
7764   let Inst{15} = b15_b12{1};
7765   let Inst{14} = 0;
7766   let Inst{13} = shift{0};
7767   let Inst{12} = b15_b12{0};
7770 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7771                                       string asm> {
7772   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7773                                                  asm, ".4h", []>;
7774   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7775                                                  asm, ".8h", []>;
7777   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7778                                              asm, ".2s", []>;
7779   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7780                                              asm, ".4s", []>;
7783 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7784                                       bits<2> w_cmode, string asm,
7785                                       SDNode OpNode> {
7786   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7787                                                  asm, ".4h",
7788              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7789                                              imm0_255:$imm8,
7790                                              (i32 imm:$shift)))]>;
7791   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7792                                                  asm, ".8h",
7793              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7794                                               imm0_255:$imm8,
7795                                               (i32 imm:$shift)))]>;
7797   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7798                                              asm, ".2s",
7799              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7800                                              imm0_255:$imm8,
7801                                              (i32 imm:$shift)))]>;
7802   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7803                                              asm, ".4s",
7804              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7805                                               imm0_255:$imm8,
7806                                               (i32 imm:$shift)))]>;
7809 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7810                              RegisterOperand vectype, string asm,
7811                              string kind, list<dag> pattern>
7812   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7813                               (ins move_vec_shift:$shift),
7814                               "$shift", asm, kind, pattern> {
7815   bits<1> shift;
7816   let Inst{15-13} = cmode{3-1};
7817   let Inst{12}    = shift;
7820 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7821                                    RegisterOperand vectype,
7822                                    Operand imm_type, string asm,
7823                                    string kind, list<dag> pattern>
7824   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7825                               asm, kind, pattern> {
7826   let Inst{15-12} = cmode;
7829 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7830                                    list<dag> pattern>
7831   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7832                         "\t$Rd, $imm8", "", pattern> {
7833   let Inst{15-12} = cmode;
7834   let DecoderMethod = "DecodeModImmInstruction";
7837 //----------------------------------------------------------------------------
7838 // AdvSIMD indexed element
7839 //----------------------------------------------------------------------------
7841 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7842 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7843                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7844                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7845                       string apple_kind, string dst_kind, string lhs_kind,
7846                       string rhs_kind, list<dag> pattern>
7847   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7848       asm,
7849       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7850       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7851     Sched<[WriteV]> {
7852   bits<5> Rd;
7853   bits<5> Rn;
7854   bits<5> Rm;
7856   let Inst{31}    = 0;
7857   let Inst{30}    = Q;
7858   let Inst{29}    = U;
7859   let Inst{28}    = Scalar;
7860   let Inst{27-24} = 0b1111;
7861   let Inst{23-22} = size;
7862   // Bit 21 must be set by the derived class.
7863   let Inst{20-16} = Rm;
7864   let Inst{15-12} = opc;
7865   // Bit 11 must be set by the derived class.
7866   let Inst{10}    = 0;
7867   let Inst{9-5}   = Rn;
7868   let Inst{4-0}   = Rd;
7871 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7872 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7873                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7874                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7875                       string apple_kind, string dst_kind, string lhs_kind,
7876                       string rhs_kind, list<dag> pattern>
7877   : I<(outs dst_reg:$dst),
7878       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7879       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7880       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7881     Sched<[WriteV]> {
7882   bits<5> Rd;
7883   bits<5> Rn;
7884   bits<5> Rm;
7886   let Inst{31}    = 0;
7887   let Inst{30}    = Q;
7888   let Inst{29}    = U;
7889   let Inst{28}    = Scalar;
7890   let Inst{27-24} = 0b1111;
7891   let Inst{23-22} = size;
7892   // Bit 21 must be set by the derived class.
7893   let Inst{20-16} = Rm;
7894   let Inst{15-12} = opc;
7895   // Bit 11 must be set by the derived class.
7896   let Inst{10}    = 0;
7897   let Inst{9-5}   = Rn;
7898   let Inst{4-0}   = Rd;
7902 //----------------------------------------------------------------------------
7903 // Armv8.6 BFloat16 Extension
7904 //----------------------------------------------------------------------------
7905 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
7907 class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
7908                                    string kind2, RegisterOperand RegType,
7909                                    ValueType AccumType, ValueType InputType>
7910   : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
7911                     (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
7912                                             (InputType RegType:$Rn),
7913                                             (InputType RegType:$Rm)))]> {
7914   let AsmString = !strconcat(asm,
7915                              "{\t$Rd" # kind1 # ", $Rn" # kind2 #
7916                                ", $Rm" # kind2 # "}");
7919 multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
7920   def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
7921                                            v2f32, v4bf16>;
7922   def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
7923                                            v4f32, v8bf16>;
7926 class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
7927                                       string dst_kind, string lhs_kind,
7928                                       string rhs_kind,
7929                                       RegisterOperand RegType,
7930                                       ValueType AccumType,
7931                                       ValueType InputType>
7932   : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
7933                         RegType, RegType, V128, VectorIndexS,
7934                         asm, "", dst_kind, lhs_kind, rhs_kind,
7935         [(set (AccumType RegType:$dst),
7936               (AccumType (int_aarch64_neon_bfdot
7937                                  (AccumType RegType:$Rd),
7938                                  (InputType RegType:$Rn),
7939                                  (InputType (bitconvert (AccumType
7940                                     (AArch64duplane32 (v4f32 V128:$Rm),
7941                                         VectorIndexS:$idx)))))))]> {
7943   bits<2> idx;
7944   let Inst{21}    = idx{0};  // L
7945   let Inst{11}    = idx{1};  // H
7948 multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
7950   def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
7951                                                ".2h", V64, v2f32, v4bf16>;
7952   def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
7953                                               ".2h", V128, v4f32, v8bf16>;
7956 class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
7957   : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
7958               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
7959                                                (v8bf16 V128:$Rn),
7960                                                (v8bf16 V128:$Rm)))]> {
7961   let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
7964 class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
7965   : I<(outs V128:$dst),
7966       (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
7967       "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
7968           [(set (v4f32 V128:$dst),
7969                 (v4f32 (OpNode (v4f32 V128:$Rd),
7970                                (v8bf16 V128:$Rn),
7971                                (v8bf16
7972                                   (AArch64duplane16 (v8bf16 V128_lo:$Rm),
7973                                       VectorIndexH:$idx)))))]>,
7974     Sched<[WriteV]> {
7975   bits<5> Rd;
7976   bits<5> Rn;
7977   bits<4> Rm;
7978   bits<3> idx;
7980   let Inst{31}    = 0;
7981   let Inst{30}    = Q;
7982   let Inst{29-22} = 0b00111111;
7983   let Inst{21-20} = idx{1-0};
7984   let Inst{19-16} = Rm;
7985   let Inst{15-12} = 0b1111;
7986   let Inst{11}    = idx{2};   // H
7987   let Inst{10}    = 0;
7988   let Inst{9-5}   = Rn;
7989   let Inst{4-0}   = Rd;
7992 class SIMDThreeSameVectorBF16MatrixMul<string asm>
7993   : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
7994                                 V128, asm, ".4s",
7995                           [(set (v4f32 V128:$dst),
7996                                 (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
7997                                                          (v8bf16 V128:$Rn),
7998                                                          (v8bf16 V128:$Rm)))]> {
7999   let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8000                                     ", $Rm", ".8h", "}");
8003 class SIMD_BFCVTN
8004   : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8005                            "bfcvtn", ".4h", ".4s",
8006     [(set (v8bf16 V128:$Rd),
8007           (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8009 class SIMD_BFCVTN2
8010   : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8011                            "bfcvtn2", ".8h", ".4s",
8012     [(set (v8bf16 V128:$dst),
8013           (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8015 class BF16ToSinglePrecision<string asm>
8016   : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8017     [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8018     Sched<[WriteFCvt]> {
8019   bits<5> Rd;
8020   bits<5> Rn;
8021   let Inst{31-10} = 0b0001111001100011010000;
8022   let Inst{9-5}   = Rn;
8023   let Inst{4-0}   = Rd;
8025 } // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8027 //----------------------------------------------------------------------------
8028 // Armv8.6 Matrix Multiply Extension
8029 //----------------------------------------------------------------------------
8031 class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8032   : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8033               [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8034                                                (v16i8 V128:$Rn),
8035                                                (v16i8 V128:$Rm)))]> {
8036   let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8039 //----------------------------------------------------------------------------
8040 // ARMv8.2-A Dot Product Instructions (Indexed)
8041 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8042                                       string dst_kind, string lhs_kind, string rhs_kind,
8043                                       RegisterOperand RegType,
8044                                       ValueType AccumType, ValueType InputType,
8045                                       SDPatternOperator OpNode> :
8046         BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8047                             VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8048         [(set (AccumType RegType:$dst),
8049               (AccumType (OpNode (AccumType RegType:$Rd),
8050                                  (InputType RegType:$Rn),
8051                                  (InputType (bitconvert (AccumType
8052                                     (AArch64duplane32 (v4i32 V128:$Rm),
8053                                         VectorIndexS:$idx)))))))]> {
8054   bits<2> idx;
8055   let Inst{21}    = idx{0};  // L
8056   let Inst{11}    = idx{1};  // H
8059 multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8060                                        SDPatternOperator OpNode> {
8061   def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8062                                               V64, v2i32, v8i8, OpNode>;
8063   def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8064                                               V128, v4i32, v16i8, OpNode>;
8067 // ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8068 class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8069                                       string dst_kind, string lhs_kind,
8070                                       string rhs_kind, RegisterOperand RegType,
8071                                       ValueType AccumType, ValueType InputType,
8072                                       SDPatternOperator OpNode> :
8073         BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8074                             VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8075           [(set (AccumType RegType:$dst),
8076                 (AccumType (OpNode (AccumType RegType:$Rd),
8077                                    (InputType RegType:$Rn),
8078                                    (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8079                                                 VectorIndexH:$idx)))))]> {
8080   // idx = H:L:M
8081   bits<3> idx;
8082   let Inst{11} = idx{2}; // H
8083   let Inst{21} = idx{1}; // L
8084   let Inst{20} = idx{0}; // M
8087 multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8088                                        SDPatternOperator OpNode> {
8089   def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8090                                               V64, v2f32, v4f16, OpNode>;
8091   def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8092                                               V128, v4f32, v8f16, OpNode>;
8095 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8096                          SDPatternOperator OpNode> {
8097   let Predicates = [HasNEON, HasFullFP16] in {
8098   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8099                                       V64, V64,
8100                                       V128_lo, VectorIndexH,
8101                                       asm, ".4h", ".4h", ".4h", ".h",
8102     [(set (v4f16 V64:$Rd),
8103         (OpNode (v4f16 V64:$Rn),
8104          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8105     bits<3> idx;
8106     let Inst{11} = idx{2};
8107     let Inst{21} = idx{1};
8108     let Inst{20} = idx{0};
8109   }
8111   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8112                                       V128, V128,
8113                                       V128_lo, VectorIndexH,
8114                                       asm, ".8h", ".8h", ".8h", ".h",
8115     [(set (v8f16 V128:$Rd),
8116         (OpNode (v8f16 V128:$Rn),
8117          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8118     bits<3> idx;
8119     let Inst{11} = idx{2};
8120     let Inst{21} = idx{1};
8121     let Inst{20} = idx{0};
8122   }
8123   } // Predicates = [HasNEON, HasFullFP16]
8125   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8126                                       V64, V64,
8127                                       V128, VectorIndexS,
8128                                       asm, ".2s", ".2s", ".2s", ".s",
8129     [(set (v2f32 V64:$Rd),
8130         (OpNode (v2f32 V64:$Rn),
8131          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8132     bits<2> idx;
8133     let Inst{11} = idx{1};
8134     let Inst{21} = idx{0};
8135   }
8137   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8138                                       V128, V128,
8139                                       V128, VectorIndexS,
8140                                       asm, ".4s", ".4s", ".4s", ".s",
8141     [(set (v4f32 V128:$Rd),
8142         (OpNode (v4f32 V128:$Rn),
8143          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8144     bits<2> idx;
8145     let Inst{11} = idx{1};
8146     let Inst{21} = idx{0};
8147   }
8149   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8150                                       V128, V128,
8151                                       V128, VectorIndexD,
8152                                       asm, ".2d", ".2d", ".2d", ".d",
8153     [(set (v2f64 V128:$Rd),
8154         (OpNode (v2f64 V128:$Rn),
8155          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8156     bits<1> idx;
8157     let Inst{11} = idx{0};
8158     let Inst{21} = 0;
8159   }
8161   let Predicates = [HasNEON, HasFullFP16] in {
8162   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8163                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8164                                       asm, ".h", "", "", ".h",
8165     [(set (f16 FPR16Op:$Rd),
8166           (OpNode (f16 FPR16Op:$Rn),
8167                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
8168                                        VectorIndexH:$idx))))]> {
8169     bits<3> idx;
8170     let Inst{11} = idx{2};
8171     let Inst{21} = idx{1};
8172     let Inst{20} = idx{0};
8173   }
8174   } // Predicates = [HasNEON, HasFullFP16]
8176   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8177                                       FPR32Op, FPR32Op, V128, VectorIndexS,
8178                                       asm, ".s", "", "", ".s",
8179     [(set (f32 FPR32Op:$Rd),
8180           (OpNode (f32 FPR32Op:$Rn),
8181                   (f32 (vector_extract (v4f32 V128:$Rm),
8182                                        VectorIndexS:$idx))))]> {
8183     bits<2> idx;
8184     let Inst{11} = idx{1};
8185     let Inst{21} = idx{0};
8186   }
8188   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8189                                       FPR64Op, FPR64Op, V128, VectorIndexD,
8190                                       asm, ".d", "", "", ".d",
8191     [(set (f64 FPR64Op:$Rd),
8192           (OpNode (f64 FPR64Op:$Rn),
8193                   (f64 (vector_extract (v2f64 V128:$Rm),
8194                                        VectorIndexD:$idx))))]> {
8195     bits<1> idx;
8196     let Inst{11} = idx{0};
8197     let Inst{21} = 0;
8198   }
8201 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8202   let Predicates = [HasNEON, HasFullFP16] in {
8203   // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8204   def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8205                            (AArch64duplane16 (v8f16 V128_lo:$Rm),
8206                                            VectorIndexH:$idx))),
8207             (!cast<Instruction>(INST # "v8i16_indexed")
8208                 V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8209   def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8210                            (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8211             (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8212                 (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8214   def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8215                            (AArch64duplane16 (v8f16 V128_lo:$Rm),
8216                                            VectorIndexH:$idx))),
8217             (!cast<Instruction>(INST # "v4i16_indexed")
8218                 V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8219   def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8220                            (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8221             (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8222                 (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8224   def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8225                          (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8226             (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8227                 V128_lo:$Rm, VectorIndexH:$idx)>;
8228   } // Predicates = [HasNEON, HasFullFP16]
8230   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8231   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8232                            (AArch64duplane32 (v4f32 V128:$Rm),
8233                                            VectorIndexS:$idx))),
8234             (!cast<Instruction>(INST # v2i32_indexed)
8235                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8236   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8237                            (AArch64dup (f32 FPR32Op:$Rm)))),
8238             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8239                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8242   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8243   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8244                            (AArch64duplane32 (v4f32 V128:$Rm),
8245                                            VectorIndexS:$idx))),
8246             (!cast<Instruction>(INST # "v4i32_indexed")
8247                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8248   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8249                            (AArch64dup (f32 FPR32Op:$Rm)))),
8250             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8251                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8253   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8254   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8255                            (AArch64duplane64 (v2f64 V128:$Rm),
8256                                            VectorIndexD:$idx))),
8257             (!cast<Instruction>(INST # "v2i64_indexed")
8258                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8259   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8260                            (AArch64dup (f64 FPR64Op:$Rm)))),
8261             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8262                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8264   // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8265   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8266                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8267             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8268                 V128:$Rm, VectorIndexS:$idx)>;
8270   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8271   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8272                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8273             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8274                 V128:$Rm, VectorIndexD:$idx)>;
8277 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8278   let Predicates = [HasNEON, HasFullFP16] in {
8279   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8280                                           V128_lo, VectorIndexH,
8281                                           asm, ".4h", ".4h", ".4h", ".h", []> {
8282     bits<3> idx;
8283     let Inst{11} = idx{2};
8284     let Inst{21} = idx{1};
8285     let Inst{20} = idx{0};
8286   }
8288   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8289                                           V128, V128,
8290                                           V128_lo, VectorIndexH,
8291                                           asm, ".8h", ".8h", ".8h", ".h", []> {
8292     bits<3> idx;
8293     let Inst{11} = idx{2};
8294     let Inst{21} = idx{1};
8295     let Inst{20} = idx{0};
8296   }
8297   } // Predicates = [HasNEON, HasFullFP16]
8299   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8300                                           V128, VectorIndexS,
8301                                           asm, ".2s", ".2s", ".2s", ".s", []> {
8302     bits<2> idx;
8303     let Inst{11} = idx{1};
8304     let Inst{21} = idx{0};
8305   }
8307   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8308                                       V128, V128,
8309                                       V128, VectorIndexS,
8310                                       asm, ".4s", ".4s", ".4s", ".s", []> {
8311     bits<2> idx;
8312     let Inst{11} = idx{1};
8313     let Inst{21} = idx{0};
8314   }
8316   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8317                                       V128, V128,
8318                                       V128, VectorIndexD,
8319                                       asm, ".2d", ".2d", ".2d", ".d", []> {
8320     bits<1> idx;
8321     let Inst{11} = idx{0};
8322     let Inst{21} = 0;
8323   }
8325   let Predicates = [HasNEON, HasFullFP16] in {
8326   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8327                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8328                                       asm, ".h", "", "", ".h", []> {
8329     bits<3> idx;
8330     let Inst{11} = idx{2};
8331     let Inst{21} = idx{1};
8332     let Inst{20} = idx{0};
8333   }
8334   } // Predicates = [HasNEON, HasFullFP16]
8336   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8337                                       FPR32Op, FPR32Op, V128, VectorIndexS,
8338                                       asm, ".s", "", "", ".s", []> {
8339     bits<2> idx;
8340     let Inst{11} = idx{1};
8341     let Inst{21} = idx{0};
8342   }
8344   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8345                                       FPR64Op, FPR64Op, V128, VectorIndexD,
8346                                       asm, ".d", "", "", ".d", []> {
8347     bits<1> idx;
8348     let Inst{11} = idx{0};
8349     let Inst{21} = 0;
8350   }
8353 multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8354                                  SDPatternOperator OpNodeLaneQ> {
8356   def : Pat<(v4i16 (OpNodeLane
8357                      (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8358                      VectorIndexS32b:$idx)),
8359             (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8360               (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8361               (UImmS1XForm $idx))>;
8363   def : Pat<(v4i16 (OpNodeLaneQ
8364                      (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8365                      VectorIndexH32b:$idx)),
8366             (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8367               (UImmS1XForm $idx))>;
8369   def : Pat<(v8i16 (OpNodeLane
8370                      (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8371                      VectorIndexS32b:$idx)),
8372             (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8373               (SUBREG_TO_REG (i32 0), $Rm, dsub),
8374               (UImmS1XForm $idx))>;
8376   def : Pat<(v8i16 (OpNodeLaneQ
8377                      (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8378                      VectorIndexH32b:$idx)),
8379             (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8380               (UImmS1XForm $idx))>;
8382   def : Pat<(v2i32 (OpNodeLane
8383                      (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8384                      VectorIndexD32b:$idx)),
8385             (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8386               (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8387               (UImmS1XForm $idx))>;
8389   def : Pat<(v2i32 (OpNodeLaneQ
8390                      (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8391                      VectorIndexS32b:$idx)),
8392             (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8393               (UImmS1XForm $idx))>;
8395   def : Pat<(v4i32 (OpNodeLane
8396                      (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8397                      VectorIndexD32b:$idx)),
8398             (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8399               (SUBREG_TO_REG (i32 0), $Rm, dsub),
8400               (UImmS1XForm $idx))>;
8402   def : Pat<(v4i32 (OpNodeLaneQ
8403                      (v4i32 V128:$Rn),
8404                      (v4i32 V128:$Rm),
8405                      VectorIndexS32b:$idx)),
8406             (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8407               (UImmS1XForm $idx))>;
8411 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8412                          SDPatternOperator OpNode> {
8413   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8414                                       V128_lo, VectorIndexH,
8415                                       asm, ".4h", ".4h", ".4h", ".h",
8416     [(set (v4i16 V64:$Rd),
8417         (OpNode (v4i16 V64:$Rn),
8418          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8419     bits<3> idx;
8420     let Inst{11} = idx{2};
8421     let Inst{21} = idx{1};
8422     let Inst{20} = idx{0};
8423   }
8425   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8426                                       V128, V128,
8427                                       V128_lo, VectorIndexH,
8428                                       asm, ".8h", ".8h", ".8h", ".h",
8429     [(set (v8i16 V128:$Rd),
8430        (OpNode (v8i16 V128:$Rn),
8431          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8432     bits<3> idx;
8433     let Inst{11} = idx{2};
8434     let Inst{21} = idx{1};
8435     let Inst{20} = idx{0};
8436   }
8438   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8439                                       V64, V64,
8440                                       V128, VectorIndexS,
8441                                       asm, ".2s", ".2s", ".2s",  ".s",
8442     [(set (v2i32 V64:$Rd),
8443        (OpNode (v2i32 V64:$Rn),
8444           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8445     bits<2> idx;
8446     let Inst{11} = idx{1};
8447     let Inst{21} = idx{0};
8448   }
8450   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8451                                       V128, V128,
8452                                       V128, VectorIndexS,
8453                                       asm, ".4s", ".4s", ".4s", ".s",
8454     [(set (v4i32 V128:$Rd),
8455        (OpNode (v4i32 V128:$Rn),
8456           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8457     bits<2> idx;
8458     let Inst{11} = idx{1};
8459     let Inst{21} = idx{0};
8460   }
8462   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8463                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8464                                       asm, ".h", "", "", ".h", []> {
8465     bits<3> idx;
8466     let Inst{11} = idx{2};
8467     let Inst{21} = idx{1};
8468     let Inst{20} = idx{0};
8469   }
8471   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8472                                       FPR32Op, FPR32Op, V128, VectorIndexS,
8473                                       asm, ".s", "", "", ".s",
8474       [(set (i32 FPR32Op:$Rd),
8475             (OpNode FPR32Op:$Rn,
8476                     (i32 (vector_extract (v4i32 V128:$Rm),
8477                                          VectorIndexS:$idx))))]> {
8478     bits<2> idx;
8479     let Inst{11} = idx{1};
8480     let Inst{21} = idx{0};
8481   }
8484 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8485                                SDPatternOperator OpNode> {
8486   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8487                                       V64, V64,
8488                                       V128_lo, VectorIndexH,
8489                                       asm, ".4h", ".4h", ".4h", ".h",
8490     [(set (v4i16 V64:$Rd),
8491         (OpNode (v4i16 V64:$Rn),
8492          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8493     bits<3> idx;
8494     let Inst{11} = idx{2};
8495     let Inst{21} = idx{1};
8496     let Inst{20} = idx{0};
8497   }
8499   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8500                                       V128, V128,
8501                                       V128_lo, VectorIndexH,
8502                                       asm, ".8h", ".8h", ".8h", ".h",
8503     [(set (v8i16 V128:$Rd),
8504        (OpNode (v8i16 V128:$Rn),
8505          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8506     bits<3> idx;
8507     let Inst{11} = idx{2};
8508     let Inst{21} = idx{1};
8509     let Inst{20} = idx{0};
8510   }
8512   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8513                                       V64, V64,
8514                                       V128, VectorIndexS,
8515                                       asm, ".2s", ".2s", ".2s", ".s",
8516     [(set (v2i32 V64:$Rd),
8517        (OpNode (v2i32 V64:$Rn),
8518           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8519     bits<2> idx;
8520     let Inst{11} = idx{1};
8521     let Inst{21} = idx{0};
8522   }
8524   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8525                                       V128, V128,
8526                                       V128, VectorIndexS,
8527                                       asm, ".4s", ".4s", ".4s", ".s",
8528     [(set (v4i32 V128:$Rd),
8529        (OpNode (v4i32 V128:$Rn),
8530           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8531     bits<2> idx;
8532     let Inst{11} = idx{1};
8533     let Inst{21} = idx{0};
8534   }
8537 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8538                                    SDPatternOperator OpNode> {
8539   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8540                                           V128_lo, VectorIndexH,
8541                                           asm, ".4h", ".4h", ".4h", ".h",
8542     [(set (v4i16 V64:$dst),
8543         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8544          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8545     bits<3> idx;
8546     let Inst{11} = idx{2};
8547     let Inst{21} = idx{1};
8548     let Inst{20} = idx{0};
8549   }
8551   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8552                                       V128, V128,
8553                                       V128_lo, VectorIndexH,
8554                                       asm, ".8h", ".8h", ".8h", ".h",
8555     [(set (v8i16 V128:$dst),
8556        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8557          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8558     bits<3> idx;
8559     let Inst{11} = idx{2};
8560     let Inst{21} = idx{1};
8561     let Inst{20} = idx{0};
8562   }
8564   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8565                                       V64, V64,
8566                                       V128, VectorIndexS,
8567                                       asm, ".2s", ".2s", ".2s", ".s",
8568     [(set (v2i32 V64:$dst),
8569        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8570           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8571     bits<2> idx;
8572     let Inst{11} = idx{1};
8573     let Inst{21} = idx{0};
8574   }
8576   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8577                                       V128, V128,
8578                                       V128, VectorIndexS,
8579                                       asm, ".4s", ".4s", ".4s", ".s",
8580     [(set (v4i32 V128:$dst),
8581        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8582           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8583     bits<2> idx;
8584     let Inst{11} = idx{1};
8585     let Inst{21} = idx{0};
8586   }
8589 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8590                              SDPatternOperator OpNode> {
8591   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8592                                       V128, V64,
8593                                       V128_lo, VectorIndexH,
8594                                       asm, ".4s", ".4s", ".4h", ".h",
8595     [(set (v4i32 V128:$Rd),
8596         (OpNode (v4i16 V64:$Rn),
8597          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8598     bits<3> idx;
8599     let Inst{11} = idx{2};
8600     let Inst{21} = idx{1};
8601     let Inst{20} = idx{0};
8602   }
8604   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8605                                       V128, V128,
8606                                       V128_lo, VectorIndexH,
8607                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8608     [(set (v4i32 V128:$Rd),
8609           (OpNode (extract_high_v8i16 V128:$Rn),
8610                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8611                                                       VectorIndexH:$idx))))]> {
8613     bits<3> idx;
8614     let Inst{11} = idx{2};
8615     let Inst{21} = idx{1};
8616     let Inst{20} = idx{0};
8617   }
8619   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8620                                       V128, V64,
8621                                       V128, VectorIndexS,
8622                                       asm, ".2d", ".2d", ".2s", ".s",
8623     [(set (v2i64 V128:$Rd),
8624         (OpNode (v2i32 V64:$Rn),
8625          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8626     bits<2> idx;
8627     let Inst{11} = idx{1};
8628     let Inst{21} = idx{0};
8629   }
8631   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8632                                       V128, V128,
8633                                       V128, VectorIndexS,
8634                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8635     [(set (v2i64 V128:$Rd),
8636           (OpNode (extract_high_v4i32 V128:$Rn),
8637                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8638                                                       VectorIndexS:$idx))))]> {
8639     bits<2> idx;
8640     let Inst{11} = idx{1};
8641     let Inst{21} = idx{0};
8642   }
8644   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8645                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8646                                       asm, ".h", "", "", ".h", []> {
8647     bits<3> idx;
8648     let Inst{11} = idx{2};
8649     let Inst{21} = idx{1};
8650     let Inst{20} = idx{0};
8651   }
8653   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8654                                       FPR64Op, FPR32Op, V128, VectorIndexS,
8655                                       asm, ".s", "", "", ".s", []> {
8656     bits<2> idx;
8657     let Inst{11} = idx{1};
8658     let Inst{21} = idx{0};
8659   }
8662 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8663                                        SDPatternOperator Accum> {
8664   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8665                                       V128, V64,
8666                                       V128_lo, VectorIndexH,
8667                                       asm, ".4s", ".4s", ".4h", ".h",
8668     [(set (v4i32 V128:$dst),
8669           (Accum (v4i32 V128:$Rd),
8670                  (v4i32 (int_aarch64_neon_sqdmull
8671                              (v4i16 V64:$Rn),
8672                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8673                                                     VectorIndexH:$idx))))))]> {
8674     bits<3> idx;
8675     let Inst{11} = idx{2};
8676     let Inst{21} = idx{1};
8677     let Inst{20} = idx{0};
8678   }
8680   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8681   // intermediate EXTRACT_SUBREG would be untyped.
8682   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8683                 (i32 (vector_extract (v4i32
8684                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8685                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8686                                                     VectorIndexH:$idx)))),
8687                          (i64 0))))),
8688             (EXTRACT_SUBREG
8689                 (!cast<Instruction>(NAME # v4i16_indexed)
8690                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8691                     V128_lo:$Rm, VectorIndexH:$idx),
8692                 ssub)>;
8694   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8695                                       V128, V128,
8696                                       V128_lo, VectorIndexH,
8697                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8698     [(set (v4i32 V128:$dst),
8699           (Accum (v4i32 V128:$Rd),
8700                  (v4i32 (int_aarch64_neon_sqdmull
8701                             (extract_high_v8i16 V128:$Rn),
8702                             (extract_high_v8i16
8703                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8704                                                 VectorIndexH:$idx))))))]> {
8705     bits<3> idx;
8706     let Inst{11} = idx{2};
8707     let Inst{21} = idx{1};
8708     let Inst{20} = idx{0};
8709   }
8711   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8712                                       V128, V64,
8713                                       V128, VectorIndexS,
8714                                       asm, ".2d", ".2d", ".2s", ".s",
8715     [(set (v2i64 V128:$dst),
8716         (Accum (v2i64 V128:$Rd),
8717                (v2i64 (int_aarch64_neon_sqdmull
8718                           (v2i32 V64:$Rn),
8719                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8720                                                  VectorIndexS:$idx))))))]> {
8721     bits<2> idx;
8722     let Inst{11} = idx{1};
8723     let Inst{21} = idx{0};
8724   }
8726   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8727                                       V128, V128,
8728                                       V128, VectorIndexS,
8729                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8730     [(set (v2i64 V128:$dst),
8731           (Accum (v2i64 V128:$Rd),
8732                  (v2i64 (int_aarch64_neon_sqdmull
8733                             (extract_high_v4i32 V128:$Rn),
8734                             (extract_high_v4i32
8735                                 (AArch64duplane32 (v4i32 V128:$Rm),
8736                                                 VectorIndexS:$idx))))))]> {
8737     bits<2> idx;
8738     let Inst{11} = idx{1};
8739     let Inst{21} = idx{0};
8740   }
8742   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8743                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8744                                       asm, ".h", "", "", ".h", []> {
8745     bits<3> idx;
8746     let Inst{11} = idx{2};
8747     let Inst{21} = idx{1};
8748     let Inst{20} = idx{0};
8749   }
8752   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8753                                       FPR64Op, FPR32Op, V128, VectorIndexS,
8754                                       asm, ".s", "", "", ".s",
8755     [(set (i64 FPR64Op:$dst),
8756           (Accum (i64 FPR64Op:$Rd),
8757                  (i64 (int_aarch64_neon_sqdmulls_scalar
8758                             (i32 FPR32Op:$Rn),
8759                             (i32 (vector_extract (v4i32 V128:$Rm),
8760                                                  VectorIndexS:$idx))))))]> {
8762     bits<2> idx;
8763     let Inst{11} = idx{1};
8764     let Inst{21} = idx{0};
8765   }
8768 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8769                                    SDPatternOperator OpNode> {
8770   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8771   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8772                                       V128, V64,
8773                                       V128_lo, VectorIndexH,
8774                                       asm, ".4s", ".4s", ".4h", ".h",
8775     [(set (v4i32 V128:$Rd),
8776         (OpNode (v4i16 V64:$Rn),
8777          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8778     bits<3> idx;
8779     let Inst{11} = idx{2};
8780     let Inst{21} = idx{1};
8781     let Inst{20} = idx{0};
8782   }
8784   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8785                                       V128, V128,
8786                                       V128_lo, VectorIndexH,
8787                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8788     [(set (v4i32 V128:$Rd),
8789           (OpNode (extract_high_v8i16 V128:$Rn),
8790                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8791                                                       VectorIndexH:$idx))))]> {
8793     bits<3> idx;
8794     let Inst{11} = idx{2};
8795     let Inst{21} = idx{1};
8796     let Inst{20} = idx{0};
8797   }
8799   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8800                                       V128, V64,
8801                                       V128, VectorIndexS,
8802                                       asm, ".2d", ".2d", ".2s", ".s",
8803     [(set (v2i64 V128:$Rd),
8804         (OpNode (v2i32 V64:$Rn),
8805          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8806     bits<2> idx;
8807     let Inst{11} = idx{1};
8808     let Inst{21} = idx{0};
8809   }
8811   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8812                                       V128, V128,
8813                                       V128, VectorIndexS,
8814                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8815     [(set (v2i64 V128:$Rd),
8816           (OpNode (extract_high_v4i32 V128:$Rn),
8817                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8818                                                       VectorIndexS:$idx))))]> {
8819     bits<2> idx;
8820     let Inst{11} = idx{1};
8821     let Inst{21} = idx{0};
8822   }
8823   }
8826 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8827                                        SDPatternOperator OpNode> {
8828   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8829   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8830                                       V128, V64,
8831                                       V128_lo, VectorIndexH,
8832                                       asm, ".4s", ".4s", ".4h", ".h",
8833     [(set (v4i32 V128:$dst),
8834         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8835          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8836     bits<3> idx;
8837     let Inst{11} = idx{2};
8838     let Inst{21} = idx{1};
8839     let Inst{20} = idx{0};
8840   }
8842   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8843                                       V128, V128,
8844                                       V128_lo, VectorIndexH,
8845                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8846     [(set (v4i32 V128:$dst),
8847           (OpNode (v4i32 V128:$Rd),
8848                   (extract_high_v8i16 V128:$Rn),
8849                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8850                                                       VectorIndexH:$idx))))]> {
8851     bits<3> idx;
8852     let Inst{11} = idx{2};
8853     let Inst{21} = idx{1};
8854     let Inst{20} = idx{0};
8855   }
8857   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8858                                       V128, V64,
8859                                       V128, VectorIndexS,
8860                                       asm, ".2d", ".2d", ".2s", ".s",
8861     [(set (v2i64 V128:$dst),
8862         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8863          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8864     bits<2> idx;
8865     let Inst{11} = idx{1};
8866     let Inst{21} = idx{0};
8867   }
8869   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8870                                       V128, V128,
8871                                       V128, VectorIndexS,
8872                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8873     [(set (v2i64 V128:$dst),
8874           (OpNode (v2i64 V128:$Rd),
8875                   (extract_high_v4i32 V128:$Rn),
8876                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8877                                                       VectorIndexS:$idx))))]> {
8878     bits<2> idx;
8879     let Inst{11} = idx{1};
8880     let Inst{21} = idx{0};
8881   }
8882   }
8885 //----------------------------------------------------------------------------
8886 // AdvSIMD scalar shift by immediate
8887 //----------------------------------------------------------------------------
8889 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8890 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8891                      RegisterClass regtype1, RegisterClass regtype2,
8892                      Operand immtype, string asm, list<dag> pattern>
8893   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8894       asm, "\t$Rd, $Rn, $imm", "", pattern>,
8895     Sched<[WriteV]> {
8896   bits<5> Rd;
8897   bits<5> Rn;
8898   bits<7> imm;
8899   let Inst{31-30} = 0b01;
8900   let Inst{29}    = U;
8901   let Inst{28-23} = 0b111110;
8902   let Inst{22-16} = fixed_imm;
8903   let Inst{15-11} = opc;
8904   let Inst{10}    = 1;
8905   let Inst{9-5} = Rn;
8906   let Inst{4-0} = Rd;
8909 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8910 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8911                      RegisterClass regtype1, RegisterClass regtype2,
8912                      Operand immtype, string asm, list<dag> pattern>
8913   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8914       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8915     Sched<[WriteV]> {
8916   bits<5> Rd;
8917   bits<5> Rn;
8918   bits<7> imm;
8919   let Inst{31-30} = 0b01;
8920   let Inst{29}    = U;
8921   let Inst{28-23} = 0b111110;
8922   let Inst{22-16} = fixed_imm;
8923   let Inst{15-11} = opc;
8924   let Inst{10}    = 1;
8925   let Inst{9-5} = Rn;
8926   let Inst{4-0} = Rd;
8930 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8931   let Predicates = [HasNEON, HasFullFP16] in {
8932   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8933                               FPR16, FPR16, vecshiftR16, asm, []> {
8934     let Inst{19-16} = imm{3-0};
8935   }
8936   } // Predicates = [HasNEON, HasFullFP16]
8937   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8938                               FPR32, FPR32, vecshiftR32, asm, []> {
8939     let Inst{20-16} = imm{4-0};
8940   }
8941   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8942                               FPR64, FPR64, vecshiftR64, asm, []> {
8943     let Inst{21-16} = imm{5-0};
8944   }
8947 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8948                              SDPatternOperator OpNode> {
8949   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8950                               FPR64, FPR64, vecshiftR64, asm,
8951   [(set (i64 FPR64:$Rd),
8952      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8953     let Inst{21-16} = imm{5-0};
8954   }
8956   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8957             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8960 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8961                                  SDPatternOperator OpNode = null_frag> {
8962   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8963                               FPR64, FPR64, vecshiftR64, asm,
8964   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8965                                                    (i32 vecshiftR64:$imm)))]> {
8966     let Inst{21-16} = imm{5-0};
8967   }
8969   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8970                            (i32 vecshiftR64:$imm))),
8971             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8972                                             vecshiftR64:$imm)>;
8975 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8976                              SDPatternOperator OpNode> {
8977   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8978                               FPR64, FPR64, vecshiftL64, asm,
8979     [(set (i64 FPR64:$Rd),
8980        (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8981     let Inst{21-16} = imm{5-0};
8982   }
8984   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8985             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8988 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8989 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8990   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8991                               FPR64, FPR64, vecshiftL64, asm, []> {
8992     let Inst{21-16} = imm{5-0};
8993   }
8996 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8997 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8998                                SDPatternOperator OpNode = null_frag> {
8999   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9000                               FPR8, FPR16, vecshiftR8, asm, []> {
9001     let Inst{18-16} = imm{2-0};
9002   }
9004   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9005                               FPR16, FPR32, vecshiftR16, asm, []> {
9006     let Inst{19-16} = imm{3-0};
9007   }
9009   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9010                               FPR32, FPR64, vecshiftR32, asm,
9011     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9012     let Inst{20-16} = imm{4-0};
9013   }
9016 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9017                                 SDPatternOperator OpNode> {
9018   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9019                               FPR8, FPR8, vecshiftL8, asm, []> {
9020     let Inst{18-16} = imm{2-0};
9021   }
9023   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9024                               FPR16, FPR16, vecshiftL16, asm, []> {
9025     let Inst{19-16} = imm{3-0};
9026   }
9028   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9029                               FPR32, FPR32, vecshiftL32, asm,
9030     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9031     let Inst{20-16} = imm{4-0};
9032   }
9034   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9035                               FPR64, FPR64, vecshiftL64, asm,
9036     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9037     let Inst{21-16} = imm{5-0};
9038   }
9040   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9041             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9044 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9045   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9046                               FPR8, FPR8, vecshiftR8, asm, []> {
9047     let Inst{18-16} = imm{2-0};
9048   }
9050   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9051                               FPR16, FPR16, vecshiftR16, asm, []> {
9052     let Inst{19-16} = imm{3-0};
9053   }
9055   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9056                               FPR32, FPR32, vecshiftR32, asm, []> {
9057     let Inst{20-16} = imm{4-0};
9058   }
9060   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9061                               FPR64, FPR64, vecshiftR64, asm, []> {
9062     let Inst{21-16} = imm{5-0};
9063   }
9066 //----------------------------------------------------------------------------
9067 // AdvSIMD vector x indexed element
9068 //----------------------------------------------------------------------------
9070 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9071 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9072                      RegisterOperand dst_reg, RegisterOperand src_reg,
9073                      Operand immtype,
9074                      string asm, string dst_kind, string src_kind,
9075                      list<dag> pattern>
9076   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9077       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9078            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9079     Sched<[WriteV]> {
9080   bits<5> Rd;
9081   bits<5> Rn;
9082   let Inst{31}    = 0;
9083   let Inst{30}    = Q;
9084   let Inst{29}    = U;
9085   let Inst{28-23} = 0b011110;
9086   let Inst{22-16} = fixed_imm;
9087   let Inst{15-11} = opc;
9088   let Inst{10}    = 1;
9089   let Inst{9-5}   = Rn;
9090   let Inst{4-0}   = Rd;
9093 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9094 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9095                      RegisterOperand vectype1, RegisterOperand vectype2,
9096                      Operand immtype,
9097                      string asm, string dst_kind, string src_kind,
9098                      list<dag> pattern>
9099   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9100       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9101            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9102     Sched<[WriteV]> {
9103   bits<5> Rd;
9104   bits<5> Rn;
9105   let Inst{31}    = 0;
9106   let Inst{30}    = Q;
9107   let Inst{29}    = U;
9108   let Inst{28-23} = 0b011110;
9109   let Inst{22-16} = fixed_imm;
9110   let Inst{15-11} = opc;
9111   let Inst{10}    = 1;
9112   let Inst{9-5}   = Rn;
9113   let Inst{4-0}   = Rd;
9116 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9117                               Intrinsic OpNode> {
9118   let Predicates = [HasNEON, HasFullFP16] in {
9119   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9120                                   V64, V64, vecshiftR16,
9121                                   asm, ".4h", ".4h",
9122       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9123     bits<4> imm;
9124     let Inst{19-16} = imm;
9125   }
9127   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9128                                   V128, V128, vecshiftR16,
9129                                   asm, ".8h", ".8h",
9130       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9131     bits<4> imm;
9132     let Inst{19-16} = imm;
9133   }
9134   } // Predicates = [HasNEON, HasFullFP16]
9135   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9136                                   V64, V64, vecshiftR32,
9137                                   asm, ".2s", ".2s",
9138       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9139     bits<5> imm;
9140     let Inst{20-16} = imm;
9141   }
9143   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9144                                   V128, V128, vecshiftR32,
9145                                   asm, ".4s", ".4s",
9146       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9147     bits<5> imm;
9148     let Inst{20-16} = imm;
9149   }
9151   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9152                                   V128, V128, vecshiftR64,
9153                                   asm, ".2d", ".2d",
9154       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9155     bits<6> imm;
9156     let Inst{21-16} = imm;
9157   }
9160 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9161                                   Intrinsic OpNode> {
9162   let Predicates = [HasNEON, HasFullFP16] in {
9163   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9164                                   V64, V64, vecshiftR16,
9165                                   asm, ".4h", ".4h",
9166       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9167     bits<4> imm;
9168     let Inst{19-16} = imm;
9169   }
9171   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9172                                   V128, V128, vecshiftR16,
9173                                   asm, ".8h", ".8h",
9174       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9175     bits<4> imm;
9176     let Inst{19-16} = imm;
9177   }
9178   } // Predicates = [HasNEON, HasFullFP16]
9180   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9181                                   V64, V64, vecshiftR32,
9182                                   asm, ".2s", ".2s",
9183       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9184     bits<5> imm;
9185     let Inst{20-16} = imm;
9186   }
9188   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9189                                   V128, V128, vecshiftR32,
9190                                   asm, ".4s", ".4s",
9191       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9192     bits<5> imm;
9193     let Inst{20-16} = imm;
9194   }
9196   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9197                                   V128, V128, vecshiftR64,
9198                                   asm, ".2d", ".2d",
9199       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9200     bits<6> imm;
9201     let Inst{21-16} = imm;
9202   }
9205 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9206                                      SDPatternOperator OpNode> {
9207   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9208                                   V64, V128, vecshiftR16Narrow,
9209                                   asm, ".8b", ".8h",
9210       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9211     bits<3> imm;
9212     let Inst{18-16} = imm;
9213   }
9215   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9216                                   V128, V128, vecshiftR16Narrow,
9217                                   asm#"2", ".16b", ".8h", []> {
9218     bits<3> imm;
9219     let Inst{18-16} = imm;
9220     let hasSideEffects = 0;
9221   }
9223   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9224                                   V64, V128, vecshiftR32Narrow,
9225                                   asm, ".4h", ".4s",
9226       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9227     bits<4> imm;
9228     let Inst{19-16} = imm;
9229   }
9231   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9232                                   V128, V128, vecshiftR32Narrow,
9233                                   asm#"2", ".8h", ".4s", []> {
9234     bits<4> imm;
9235     let Inst{19-16} = imm;
9236     let hasSideEffects = 0;
9237   }
9239   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9240                                   V64, V128, vecshiftR64Narrow,
9241                                   asm, ".2s", ".2d",
9242       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9243     bits<5> imm;
9244     let Inst{20-16} = imm;
9245   }
9247   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9248                                   V128, V128, vecshiftR64Narrow,
9249                                   asm#"2", ".4s", ".2d", []> {
9250     bits<5> imm;
9251     let Inst{20-16} = imm;
9252     let hasSideEffects = 0;
9253   }
9255   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9256   // themselves, so put them here instead.
9258   // Patterns involving what's effectively an insert high and a normal
9259   // intrinsic, represented by CONCAT_VECTORS.
9260   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9261                                                    vecshiftR16Narrow:$imm)),
9262             (!cast<Instruction>(NAME # "v16i8_shift")
9263                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9264                 V128:$Rn, vecshiftR16Narrow:$imm)>;
9265   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9266                                                      vecshiftR32Narrow:$imm)),
9267             (!cast<Instruction>(NAME # "v8i16_shift")
9268                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9269                 V128:$Rn, vecshiftR32Narrow:$imm)>;
9270   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9271                                                      vecshiftR64Narrow:$imm)),
9272             (!cast<Instruction>(NAME # "v4i32_shift")
9273                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9274                 V128:$Rn, vecshiftR64Narrow:$imm)>;
9277 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9278                                 SDPatternOperator OpNode> {
9279   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9280                                   V64, V64, vecshiftL8,
9281                                   asm, ".8b", ".8b",
9282                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9283                        (i32 vecshiftL8:$imm)))]> {
9284     bits<3> imm;
9285     let Inst{18-16} = imm;
9286   }
9288   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9289                                   V128, V128, vecshiftL8,
9290                                   asm, ".16b", ".16b",
9291              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9292                    (i32 vecshiftL8:$imm)))]> {
9293     bits<3> imm;
9294     let Inst{18-16} = imm;
9295   }
9297   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9298                                   V64, V64, vecshiftL16,
9299                                   asm, ".4h", ".4h",
9300               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9301                     (i32 vecshiftL16:$imm)))]> {
9302     bits<4> imm;
9303     let Inst{19-16} = imm;
9304   }
9306   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9307                                   V128, V128, vecshiftL16,
9308                                   asm, ".8h", ".8h",
9309             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9310                   (i32 vecshiftL16:$imm)))]> {
9311     bits<4> imm;
9312     let Inst{19-16} = imm;
9313   }
9315   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9316                                   V64, V64, vecshiftL32,
9317                                   asm, ".2s", ".2s",
9318               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9319                     (i32 vecshiftL32:$imm)))]> {
9320     bits<5> imm;
9321     let Inst{20-16} = imm;
9322   }
9324   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9325                                   V128, V128, vecshiftL32,
9326                                   asm, ".4s", ".4s",
9327             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9328                   (i32 vecshiftL32:$imm)))]> {
9329     bits<5> imm;
9330     let Inst{20-16} = imm;
9331   }
9333   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9334                                   V128, V128, vecshiftL64,
9335                                   asm, ".2d", ".2d",
9336             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9337                   (i32 vecshiftL64:$imm)))]> {
9338     bits<6> imm;
9339     let Inst{21-16} = imm;
9340   }
9343 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9344                                 SDPatternOperator OpNode> {
9345   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9346                                   V64, V64, vecshiftR8,
9347                                   asm, ".8b", ".8b",
9348                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9349                        (i32 vecshiftR8:$imm)))]> {
9350     bits<3> imm;
9351     let Inst{18-16} = imm;
9352   }
9354   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9355                                   V128, V128, vecshiftR8,
9356                                   asm, ".16b", ".16b",
9357              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9358                    (i32 vecshiftR8:$imm)))]> {
9359     bits<3> imm;
9360     let Inst{18-16} = imm;
9361   }
9363   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9364                                   V64, V64, vecshiftR16,
9365                                   asm, ".4h", ".4h",
9366               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9367                     (i32 vecshiftR16:$imm)))]> {
9368     bits<4> imm;
9369     let Inst{19-16} = imm;
9370   }
9372   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9373                                   V128, V128, vecshiftR16,
9374                                   asm, ".8h", ".8h",
9375             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9376                   (i32 vecshiftR16:$imm)))]> {
9377     bits<4> imm;
9378     let Inst{19-16} = imm;
9379   }
9381   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9382                                   V64, V64, vecshiftR32,
9383                                   asm, ".2s", ".2s",
9384               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9385                     (i32 vecshiftR32:$imm)))]> {
9386     bits<5> imm;
9387     let Inst{20-16} = imm;
9388   }
9390   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9391                                   V128, V128, vecshiftR32,
9392                                   asm, ".4s", ".4s",
9393             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9394                   (i32 vecshiftR32:$imm)))]> {
9395     bits<5> imm;
9396     let Inst{20-16} = imm;
9397   }
9399   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9400                                   V128, V128, vecshiftR64,
9401                                   asm, ".2d", ".2d",
9402             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9403                   (i32 vecshiftR64:$imm)))]> {
9404     bits<6> imm;
9405     let Inst{21-16} = imm;
9406   }
9409 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9410 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9411                                     SDPatternOperator OpNode = null_frag> {
9412   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9413                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
9414                  [(set (v8i8 V64:$dst),
9415                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9416                            (i32 vecshiftR8:$imm)))]> {
9417     bits<3> imm;
9418     let Inst{18-16} = imm;
9419   }
9421   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9422                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
9423              [(set (v16i8 V128:$dst),
9424                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9425                        (i32 vecshiftR8:$imm)))]> {
9426     bits<3> imm;
9427     let Inst{18-16} = imm;
9428   }
9430   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9431                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
9432               [(set (v4i16 V64:$dst),
9433                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9434                         (i32 vecshiftR16:$imm)))]> {
9435     bits<4> imm;
9436     let Inst{19-16} = imm;
9437   }
9439   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9440                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
9441             [(set (v8i16 V128:$dst),
9442               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9443                       (i32 vecshiftR16:$imm)))]> {
9444     bits<4> imm;
9445     let Inst{19-16} = imm;
9446   }
9448   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9449                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
9450               [(set (v2i32 V64:$dst),
9451                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9452                         (i32 vecshiftR32:$imm)))]> {
9453     bits<5> imm;
9454     let Inst{20-16} = imm;
9455   }
9457   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9458                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
9459             [(set (v4i32 V128:$dst),
9460               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9461                       (i32 vecshiftR32:$imm)))]> {
9462     bits<5> imm;
9463     let Inst{20-16} = imm;
9464   }
9466   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9467                                   V128, V128, vecshiftR64,
9468                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9469               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9470                       (i32 vecshiftR64:$imm)))]> {
9471     bits<6> imm;
9472     let Inst{21-16} = imm;
9473   }
9476 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9477                                     SDPatternOperator OpNode = null_frag> {
9478   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9479                                   V64, V64, vecshiftL8,
9480                                   asm, ".8b", ".8b",
9481                     [(set (v8i8 V64:$dst),
9482                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9483                                   (i32 vecshiftL8:$imm)))]> {
9484     bits<3> imm;
9485     let Inst{18-16} = imm;
9486   }
9488   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9489                                   V128, V128, vecshiftL8,
9490                                   asm, ".16b", ".16b",
9491                     [(set (v16i8 V128:$dst),
9492                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9493                                   (i32 vecshiftL8:$imm)))]> {
9494     bits<3> imm;
9495     let Inst{18-16} = imm;
9496   }
9498   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9499                                   V64, V64, vecshiftL16,
9500                                   asm, ".4h", ".4h",
9501                     [(set (v4i16 V64:$dst),
9502                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9503                                    (i32 vecshiftL16:$imm)))]> {
9504     bits<4> imm;
9505     let Inst{19-16} = imm;
9506   }
9508   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9509                                   V128, V128, vecshiftL16,
9510                                   asm, ".8h", ".8h",
9511                     [(set (v8i16 V128:$dst),
9512                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9513                                   (i32 vecshiftL16:$imm)))]> {
9514     bits<4> imm;
9515     let Inst{19-16} = imm;
9516   }
9518   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9519                                   V64, V64, vecshiftL32,
9520                                   asm, ".2s", ".2s",
9521                     [(set (v2i32 V64:$dst),
9522                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9523                                   (i32 vecshiftL32:$imm)))]> {
9524     bits<5> imm;
9525     let Inst{20-16} = imm;
9526   }
9528   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9529                                   V128, V128, vecshiftL32,
9530                                   asm, ".4s", ".4s",
9531                     [(set (v4i32 V128:$dst),
9532                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9533                                   (i32 vecshiftL32:$imm)))]> {
9534     bits<5> imm;
9535     let Inst{20-16} = imm;
9536   }
9538   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9539                                   V128, V128, vecshiftL64,
9540                                   asm, ".2d", ".2d",
9541                     [(set (v2i64 V128:$dst),
9542                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9543                                   (i32 vecshiftL64:$imm)))]> {
9544     bits<6> imm;
9545     let Inst{21-16} = imm;
9546   }
9549 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9550                                    SDPatternOperator OpNode> {
9551   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9552                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
9553       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9554     bits<3> imm;
9555     let Inst{18-16} = imm;
9556   }
9558   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9559                                   V128, V128, vecshiftL8,
9560                                   asm#"2", ".8h", ".16b",
9561       [(set (v8i16 V128:$Rd),
9562             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9563     bits<3> imm;
9564     let Inst{18-16} = imm;
9565   }
9567   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9568                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
9569       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9570     bits<4> imm;
9571     let Inst{19-16} = imm;
9572   }
9574   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9575                                   V128, V128, vecshiftL16,
9576                                   asm#"2", ".4s", ".8h",
9577       [(set (v4i32 V128:$Rd),
9578             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9580     bits<4> imm;
9581     let Inst{19-16} = imm;
9582   }
9584   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9585                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
9586       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9587     bits<5> imm;
9588     let Inst{20-16} = imm;
9589   }
9591   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9592                                   V128, V128, vecshiftL32,
9593                                   asm#"2", ".2d", ".4s",
9594       [(set (v2i64 V128:$Rd),
9595             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9596     bits<5> imm;
9597     let Inst{20-16} = imm;
9598   }
9602 //---
9603 // Vector load/store
9604 //---
9605 // SIMD ldX/stX no-index memory references don't allow the optional
9606 // ", #0" constant and handle post-indexing explicitly, so we use
9607 // a more specialized parse method for them. Otherwise, it's the same as
9608 // the general GPR64sp handling.
9610 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9611                    string asm, dag oops, dag iops, list<dag> pattern>
9612   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9613   bits<5> Vt;
9614   bits<5> Rn;
9615   let Inst{31} = 0;
9616   let Inst{30} = Q;
9617   let Inst{29-23} = 0b0011000;
9618   let Inst{22} = L;
9619   let Inst{21-16} = 0b000000;
9620   let Inst{15-12} = opcode;
9621   let Inst{11-10} = size;
9622   let Inst{9-5} = Rn;
9623   let Inst{4-0} = Vt;
9626 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9627                        string asm, dag oops, dag iops>
9628   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9629   bits<5> Vt;
9630   bits<5> Rn;
9631   bits<5> Xm;
9632   let Inst{31} = 0;
9633   let Inst{30} = Q;
9634   let Inst{29-23} = 0b0011001;
9635   let Inst{22} = L;
9636   let Inst{21} = 0;
9637   let Inst{20-16} = Xm;
9638   let Inst{15-12} = opcode;
9639   let Inst{11-10} = size;
9640   let Inst{9-5} = Rn;
9641   let Inst{4-0} = Vt;
9644 // The immediate form of AdvSIMD post-indexed addressing is encoded with
9645 // register post-index addressing from the zero register.
9646 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9647                            int Offset, int Size> {
9648   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9649   //      "ld1\t$Vt, [$Rn], #16"
9650   // may get mapped to
9651   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9652   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9653                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9654                       GPR64sp:$Rn,
9655                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9656                       XZR), 1>;
9658   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9659   //      "ld1.8b\t$Vt, [$Rn], #16"
9660   // may get mapped to
9661   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9662   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9663                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9664                       GPR64sp:$Rn,
9665                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9666                       XZR), 0>;
9668   // E.g. "ld1.8b { v0, v1 }, [x1]"
9669   //      "ld1\t$Vt, [$Rn]"
9670   // may get mapped to
9671   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9672   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9673                   (!cast<Instruction>(BaseName # Count # "v" # layout)
9674                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9675                       GPR64sp:$Rn), 0>;
9677   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9678   //      "ld1\t$Vt, [$Rn], $Xm"
9679   // may get mapped to
9680   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9681   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9682                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9683                       GPR64sp:$Rn,
9684                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9685                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9688 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9689                        int Offset128, int Offset64, bits<4> opcode> {
9690   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9691     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9692                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9693                            (ins GPR64sp:$Rn), []>;
9694     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9695                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9696                            (ins GPR64sp:$Rn), []>;
9697     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9698                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9699                            (ins GPR64sp:$Rn), []>;
9700     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9701                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9702                            (ins GPR64sp:$Rn), []>;
9703     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9704                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9705                            (ins GPR64sp:$Rn), []>;
9706     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9707                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9708                            (ins GPR64sp:$Rn), []>;
9709     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9710                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9711                            (ins GPR64sp:$Rn), []>;
9714     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9715                        (outs GPR64sp:$wback,
9716                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
9717                        (ins GPR64sp:$Rn,
9718                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9719     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9720                        (outs GPR64sp:$wback,
9721                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
9722                        (ins GPR64sp:$Rn,
9723                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9724     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9725                        (outs GPR64sp:$wback,
9726                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
9727                        (ins GPR64sp:$Rn,
9728                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9729     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9730                        (outs GPR64sp:$wback,
9731                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
9732                        (ins GPR64sp:$Rn,
9733                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9734     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9735                        (outs GPR64sp:$wback,
9736                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
9737                        (ins GPR64sp:$Rn,
9738                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9739     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9740                        (outs GPR64sp:$wback,
9741                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
9742                        (ins GPR64sp:$Rn,
9743                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9744     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9745                        (outs GPR64sp:$wback,
9746                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
9747                        (ins GPR64sp:$Rn,
9748                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9749   }
9751   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9752   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9753   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9754   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9755   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9756   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9757   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9760 // Only ld1/st1 has a v1d version.
9761 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9762                        int Offset128, int Offset64, bits<4> opcode> {
9763   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9764     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9765                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9766                                  GPR64sp:$Rn), []>;
9767     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9768                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9769                                 GPR64sp:$Rn), []>;
9770     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9771                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9772                                 GPR64sp:$Rn), []>;
9773     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9774                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9775                                 GPR64sp:$Rn), []>;
9776     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9777                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9778                                 GPR64sp:$Rn), []>;
9779     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9780                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9781                                 GPR64sp:$Rn), []>;
9782     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9783                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9784                                 GPR64sp:$Rn), []>;
9786     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9787                        (outs GPR64sp:$wback),
9788                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9789                             GPR64sp:$Rn,
9790                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9791     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9792                        (outs GPR64sp:$wback),
9793                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9794                             GPR64sp:$Rn,
9795                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9796     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9797                        (outs GPR64sp:$wback),
9798                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9799                             GPR64sp:$Rn,
9800                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9801     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9802                        (outs GPR64sp:$wback),
9803                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9804                             GPR64sp:$Rn,
9805                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9806     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9807                        (outs GPR64sp:$wback),
9808                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9809                             GPR64sp:$Rn,
9810                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9811     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9812                        (outs GPR64sp:$wback),
9813                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9814                             GPR64sp:$Rn,
9815                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9816     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9817                        (outs GPR64sp:$wback),
9818                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9819                             GPR64sp:$Rn,
9820                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9821   }
9823   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9824   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9825   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9826   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9827   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9828   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9829   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9832 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9833                        int Offset128, int Offset64, bits<4> opcode>
9834   : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9836   // LD1 instructions have extra "1d" variants.
9837   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9838     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9839                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9840                            (ins GPR64sp:$Rn), []>;
9842     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9843                        (outs GPR64sp:$wback,
9844                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
9845                        (ins GPR64sp:$Rn,
9846                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9847   }
9849   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9852 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9853                        int Offset128, int Offset64, bits<4> opcode>
9854   : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9856   // ST1 instructions have extra "1d" variants.
9857   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9858     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9859                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9860                                 GPR64sp:$Rn), []>;
9862     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9863                        (outs GPR64sp:$wback),
9864                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9865                             GPR64sp:$Rn,
9866                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9867   }
9869   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9872 multiclass SIMDLd1Multiple<string asm> {
9873   defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9874   defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9875   defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9876   defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9879 multiclass SIMDSt1Multiple<string asm> {
9880   defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9881   defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9882   defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9883   defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9886 multiclass SIMDLd2Multiple<string asm> {
9887   defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9890 multiclass SIMDSt2Multiple<string asm> {
9891   defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9894 multiclass SIMDLd3Multiple<string asm> {
9895   defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9898 multiclass SIMDSt3Multiple<string asm> {
9899   defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9902 multiclass SIMDLd4Multiple<string asm> {
9903   defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9906 multiclass SIMDSt4Multiple<string asm> {
9907   defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9910 //---
9911 // AdvSIMD Load/store single-element
9912 //---
9914 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9915                          string asm, string operands, string cst,
9916                          dag oops, dag iops, list<dag> pattern>
9917   : I<oops, iops, asm, operands, cst, pattern> {
9918   bits<5> Vt;
9919   bits<5> Rn;
9920   let Inst{31} = 0;
9921   let Inst{29-24} = 0b001101;
9922   let Inst{22} = L;
9923   let Inst{21} = R;
9924   let Inst{15-13} = opcode;
9925   let Inst{9-5} = Rn;
9926   let Inst{4-0} = Vt;
9929 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9930                          string asm, string operands, string cst,
9931                          dag oops, dag iops, list<dag> pattern>
9932   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9933   bits<5> Vt;
9934   bits<5> Rn;
9935   let Inst{31} = 0;
9936   let Inst{29-24} = 0b001101;
9937   let Inst{22} = L;
9938   let Inst{21} = R;
9939   let Inst{15-13} = opcode;
9940   let Inst{9-5} = Rn;
9941   let Inst{4-0} = Vt;
9945 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9946 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9947                   DAGOperand listtype>
9948   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9949                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
9950                        []> {
9951   let Inst{30} = Q;
9952   let Inst{23} = 0;
9953   let Inst{20-16} = 0b00000;
9954   let Inst{12} = S;
9955   let Inst{11-10} = size;
9957 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9958 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9959                       string asm, DAGOperand listtype, DAGOperand GPR64pi>
9960   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9961                        "$Rn = $wback",
9962                        (outs GPR64sp:$wback, listtype:$Vt),
9963                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9964   bits<5> Xm;
9965   let Inst{30} = Q;
9966   let Inst{23} = 1;
9967   let Inst{20-16} = Xm;
9968   let Inst{12} = S;
9969   let Inst{11-10} = size;
9972 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9973                           int Offset, int Size> {
9974   // E.g. "ld1r { v0.8b }, [x1], #1"
9975   //      "ld1r.8b\t$Vt, [$Rn], #1"
9976   // may get mapped to
9977   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9978   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9979                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9980                       GPR64sp:$Rn,
9981                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9982                       XZR), 1>;
9984   // E.g. "ld1r.8b { v0 }, [x1], #1"
9985   //      "ld1r.8b\t$Vt, [$Rn], #1"
9986   // may get mapped to
9987   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9988   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9989                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9990                       GPR64sp:$Rn,
9991                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9992                       XZR), 0>;
9994   // E.g. "ld1r.8b { v0 }, [x1]"
9995   //      "ld1r.8b\t$Vt, [$Rn]"
9996   // may get mapped to
9997   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9998   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9999                   (!cast<Instruction>(BaseName # "v" # layout)
10000                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10001                       GPR64sp:$Rn), 0>;
10003   // E.g. "ld1r.8b { v0 }, [x1], x2"
10004   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10005   // may get mapped to
10006   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10007   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10008                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10009                       GPR64sp:$Rn,
10010                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10011                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10014 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10015   int Offset1, int Offset2, int Offset4, int Offset8> {
10016   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10017                         !cast<DAGOperand>("VecList" # Count # "8b")>;
10018   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10019                         !cast<DAGOperand>("VecList" # Count #"16b")>;
10020   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10021                         !cast<DAGOperand>("VecList" # Count #"4h")>;
10022   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10023                         !cast<DAGOperand>("VecList" # Count #"8h")>;
10024   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10025                         !cast<DAGOperand>("VecList" # Count #"2s")>;
10026   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10027                         !cast<DAGOperand>("VecList" # Count #"4s")>;
10028   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10029                         !cast<DAGOperand>("VecList" # Count #"1d")>;
10030   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10031                         !cast<DAGOperand>("VecList" # Count #"2d")>;
10033   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10034                                  !cast<DAGOperand>("VecList" # Count # "8b"),
10035                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
10036   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10037                                  !cast<DAGOperand>("VecList" # Count # "16b"),
10038                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
10039   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10040                                  !cast<DAGOperand>("VecList" # Count # "4h"),
10041                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
10042   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10043                                  !cast<DAGOperand>("VecList" # Count # "8h"),
10044                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
10045   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10046                                  !cast<DAGOperand>("VecList" # Count # "2s"),
10047                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
10048   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10049                                  !cast<DAGOperand>("VecList" # Count # "4s"),
10050                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
10051   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10052                                  !cast<DAGOperand>("VecList" # Count # "1d"),
10053                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
10054   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10055                                  !cast<DAGOperand>("VecList" # Count # "2d"),
10056                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
10058   defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10059   defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10060   defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10061   defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10062   defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10063   defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10064   defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10065   defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10068 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10069                       dag oops, dag iops, list<dag> pattern>
10070   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10071                        pattern> {
10072   // idx encoded in Q:S:size fields.
10073   bits<4> idx;
10074   let Inst{30} = idx{3};
10075   let Inst{23} = 0;
10076   let Inst{20-16} = 0b00000;
10077   let Inst{12} = idx{2};
10078   let Inst{11-10} = idx{1-0};
10080 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10081                       dag oops, dag iops, list<dag> pattern>
10082   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10083                            oops, iops, pattern> {
10084   // idx encoded in Q:S:size fields.
10085   bits<4> idx;
10086   let Inst{30} = idx{3};
10087   let Inst{23} = 0;
10088   let Inst{20-16} = 0b00000;
10089   let Inst{12} = idx{2};
10090   let Inst{11-10} = idx{1-0};
10092 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10093                           dag oops, dag iops>
10094   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10095                        "$Rn = $wback", oops, iops, []> {
10096   // idx encoded in Q:S:size fields.
10097   bits<4> idx;
10098   bits<5> Xm;
10099   let Inst{30} = idx{3};
10100   let Inst{23} = 1;
10101   let Inst{20-16} = Xm;
10102   let Inst{12} = idx{2};
10103   let Inst{11-10} = idx{1-0};
10105 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10106                           dag oops, dag iops>
10107   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10108                            "$Rn = $wback", oops, iops, []> {
10109   // idx encoded in Q:S:size fields.
10110   bits<4> idx;
10111   bits<5> Xm;
10112   let Inst{30} = idx{3};
10113   let Inst{23} = 1;
10114   let Inst{20-16} = Xm;
10115   let Inst{12} = idx{2};
10116   let Inst{11-10} = idx{1-0};
10119 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10120                       dag oops, dag iops, list<dag> pattern>
10121   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10122                        pattern> {
10123   // idx encoded in Q:S:size<1> fields.
10124   bits<3> idx;
10125   let Inst{30} = idx{2};
10126   let Inst{23} = 0;
10127   let Inst{20-16} = 0b00000;
10128   let Inst{12} = idx{1};
10129   let Inst{11} = idx{0};
10130   let Inst{10} = size;
10132 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10133                       dag oops, dag iops, list<dag> pattern>
10134   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10135                            oops, iops, pattern> {
10136   // idx encoded in Q:S:size<1> fields.
10137   bits<3> idx;
10138   let Inst{30} = idx{2};
10139   let Inst{23} = 0;
10140   let Inst{20-16} = 0b00000;
10141   let Inst{12} = idx{1};
10142   let Inst{11} = idx{0};
10143   let Inst{10} = size;
10146 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10147                           dag oops, dag iops>
10148   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10149                        "$Rn = $wback", oops, iops, []> {
10150   // idx encoded in Q:S:size<1> fields.
10151   bits<3> idx;
10152   bits<5> Xm;
10153   let Inst{30} = idx{2};
10154   let Inst{23} = 1;
10155   let Inst{20-16} = Xm;
10156   let Inst{12} = idx{1};
10157   let Inst{11} = idx{0};
10158   let Inst{10} = size;
10160 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10161                           dag oops, dag iops>
10162   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10163                            "$Rn = $wback", oops, iops, []> {
10164   // idx encoded in Q:S:size<1> fields.
10165   bits<3> idx;
10166   bits<5> Xm;
10167   let Inst{30} = idx{2};
10168   let Inst{23} = 1;
10169   let Inst{20-16} = Xm;
10170   let Inst{12} = idx{1};
10171   let Inst{11} = idx{0};
10172   let Inst{10} = size;
10174 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10175                       dag oops, dag iops, list<dag> pattern>
10176   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10177                        pattern> {
10178   // idx encoded in Q:S fields.
10179   bits<2> idx;
10180   let Inst{30} = idx{1};
10181   let Inst{23} = 0;
10182   let Inst{20-16} = 0b00000;
10183   let Inst{12} = idx{0};
10184   let Inst{11-10} = size;
10186 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10187                       dag oops, dag iops, list<dag> pattern>
10188   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10189                            oops, iops, pattern> {
10190   // idx encoded in Q:S fields.
10191   bits<2> idx;
10192   let Inst{30} = idx{1};
10193   let Inst{23} = 0;
10194   let Inst{20-16} = 0b00000;
10195   let Inst{12} = idx{0};
10196   let Inst{11-10} = size;
10198 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10199                           string asm, dag oops, dag iops>
10200   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10201                        "$Rn = $wback", oops, iops, []> {
10202   // idx encoded in Q:S fields.
10203   bits<2> idx;
10204   bits<5> Xm;
10205   let Inst{30} = idx{1};
10206   let Inst{23} = 1;
10207   let Inst{20-16} = Xm;
10208   let Inst{12} = idx{0};
10209   let Inst{11-10} = size;
10211 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10212                           string asm, dag oops, dag iops>
10213   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10214                            "$Rn = $wback", oops, iops, []> {
10215   // idx encoded in Q:S fields.
10216   bits<2> idx;
10217   bits<5> Xm;
10218   let Inst{30} = idx{1};
10219   let Inst{23} = 1;
10220   let Inst{20-16} = Xm;
10221   let Inst{12} = idx{0};
10222   let Inst{11-10} = size;
10224 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10225                       dag oops, dag iops, list<dag> pattern>
10226   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10227                        pattern> {
10228   // idx encoded in Q field.
10229   bits<1> idx;
10230   let Inst{30} = idx;
10231   let Inst{23} = 0;
10232   let Inst{20-16} = 0b00000;
10233   let Inst{12} = 0;
10234   let Inst{11-10} = size;
10236 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10237                       dag oops, dag iops, list<dag> pattern>
10238   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10239                            oops, iops, pattern> {
10240   // idx encoded in Q field.
10241   bits<1> idx;
10242   let Inst{30} = idx;
10243   let Inst{23} = 0;
10244   let Inst{20-16} = 0b00000;
10245   let Inst{12} = 0;
10246   let Inst{11-10} = size;
10248 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10249                           string asm, dag oops, dag iops>
10250   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10251                        "$Rn = $wback", oops, iops, []> {
10252   // idx encoded in Q field.
10253   bits<1> idx;
10254   bits<5> Xm;
10255   let Inst{30} = idx;
10256   let Inst{23} = 1;
10257   let Inst{20-16} = Xm;
10258   let Inst{12} = 0;
10259   let Inst{11-10} = size;
10261 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10262                           string asm, dag oops, dag iops>
10263   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10264                            "$Rn = $wback", oops, iops, []> {
10265   // idx encoded in Q field.
10266   bits<1> idx;
10267   bits<5> Xm;
10268   let Inst{30} = idx;
10269   let Inst{23} = 1;
10270   let Inst{20-16} = Xm;
10271   let Inst{12} = 0;
10272   let Inst{11-10} = size;
10275 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10276 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10277                          RegisterOperand listtype,
10278                          RegisterOperand GPR64pi> {
10279   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10280                            (outs listtype:$dst),
10281                            (ins listtype:$Vt, VectorIndexB:$idx,
10282                                 GPR64sp:$Rn), []>;
10284   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10285                             (outs GPR64sp:$wback, listtype:$dst),
10286                             (ins listtype:$Vt, VectorIndexB:$idx,
10287                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10289 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10290 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10291                          RegisterOperand listtype,
10292                          RegisterOperand GPR64pi> {
10293   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10294                             (outs listtype:$dst),
10295                             (ins listtype:$Vt, VectorIndexH:$idx,
10296                                  GPR64sp:$Rn), []>;
10298   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10299                             (outs GPR64sp:$wback, listtype:$dst),
10300                             (ins listtype:$Vt, VectorIndexH:$idx,
10301                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10303 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10304 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10305                          RegisterOperand listtype,
10306                          RegisterOperand GPR64pi> {
10307   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10308                             (outs listtype:$dst),
10309                             (ins listtype:$Vt, VectorIndexS:$idx,
10310                                  GPR64sp:$Rn), []>;
10312   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10313                             (outs GPR64sp:$wback, listtype:$dst),
10314                             (ins listtype:$Vt, VectorIndexS:$idx,
10315                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10317 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10318 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10319                          RegisterOperand listtype, RegisterOperand GPR64pi> {
10320   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10321                             (outs listtype:$dst),
10322                             (ins listtype:$Vt, VectorIndexD:$idx,
10323                                  GPR64sp:$Rn), []>;
10325   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10326                             (outs GPR64sp:$wback, listtype:$dst),
10327                             (ins listtype:$Vt, VectorIndexD:$idx,
10328                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10330 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10331 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10332                          RegisterOperand listtype, RegisterOperand GPR64pi> {
10333   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10334                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10335                                         GPR64sp:$Rn), []>;
10337   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10338                                     (outs GPR64sp:$wback),
10339                                     (ins listtype:$Vt, VectorIndexB:$idx,
10340                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
10342 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10343 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10344                          RegisterOperand listtype, RegisterOperand GPR64pi> {
10345   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10346                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10347                                          GPR64sp:$Rn), []>;
10349   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10350                             (outs GPR64sp:$wback),
10351                             (ins listtype:$Vt, VectorIndexH:$idx,
10352                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10354 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10355 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10356                          RegisterOperand listtype, RegisterOperand GPR64pi> {
10357   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10358                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10359                                          GPR64sp:$Rn), []>;
10361   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10362                             (outs GPR64sp:$wback),
10363                             (ins listtype:$Vt, VectorIndexS:$idx,
10364                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10366 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10367 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10368                          RegisterOperand listtype, RegisterOperand GPR64pi> {
10369   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10370                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10371                                          GPR64sp:$Rn), []>;
10373   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10374                             (outs GPR64sp:$wback),
10375                             (ins listtype:$Vt, VectorIndexD:$idx,
10376                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
10379 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10380                                  string Count, int Offset, Operand idxtype> {
10381   // E.g. "ld1 { v0.8b }[0], [x1], #1"
10382   //      "ld1\t$Vt, [$Rn], #1"
10383   // may get mapped to
10384   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10385   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10386                   (!cast<Instruction>(NAME # Type  # "_POST")
10387                       GPR64sp:$Rn,
10388                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10389                       idxtype:$idx, XZR), 1>;
10391   // E.g. "ld1.8b { v0 }[0], [x1], #1"
10392   //      "ld1.8b\t$Vt, [$Rn], #1"
10393   // may get mapped to
10394   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10395   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10396                   (!cast<Instruction>(NAME # Type # "_POST")
10397                       GPR64sp:$Rn,
10398                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10399                       idxtype:$idx, XZR), 0>;
10401   // E.g. "ld1.8b { v0 }[0], [x1]"
10402   //      "ld1.8b\t$Vt, [$Rn]"
10403   // may get mapped to
10404   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10405   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10406                       (!cast<Instruction>(NAME # Type)
10407                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10408                          idxtype:$idx, GPR64sp:$Rn), 0>;
10410   // E.g. "ld1.8b { v0 }[0], [x1], x2"
10411   //      "ld1.8b\t$Vt, [$Rn], $Xm"
10412   // may get mapped to
10413   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10414   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10415                       (!cast<Instruction>(NAME # Type # "_POST")
10416                          GPR64sp:$Rn,
10417                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10418                          idxtype:$idx,
10419                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10422 multiclass SIMDLdSt1SingleAliases<string asm> {
10423   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10424   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10425   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10426   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10429 multiclass SIMDLdSt2SingleAliases<string asm> {
10430   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10431   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10432   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10433   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10436 multiclass SIMDLdSt3SingleAliases<string asm> {
10437   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10438   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10439   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10440   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10443 multiclass SIMDLdSt4SingleAliases<string asm> {
10444   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10445   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10446   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10447   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10449 } // end of 'let Predicates = [HasNEON]'
10451 //----------------------------------------------------------------------------
10452 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10453 //----------------------------------------------------------------------------
10455 let Predicates = [HasNEON, HasRDM] in {
10457 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10458                                     RegisterOperand regtype, string asm,
10459                                     string kind, list<dag> pattern>
10460   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10461                                 pattern> {
10463 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10464                                              SDPatternOperator Accum> {
10465   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10466     [(set (v4i16 V64:$dst),
10467           (Accum (v4i16 V64:$Rd),
10468                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
10469                                                    (v4i16 V64:$Rm)))))]>;
10470   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10471     [(set (v8i16 V128:$dst),
10472           (Accum (v8i16 V128:$Rd),
10473                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
10474                                                    (v8i16 V128:$Rm)))))]>;
10475   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10476     [(set (v2i32 V64:$dst),
10477           (Accum (v2i32 V64:$Rd),
10478                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
10479                                                    (v2i32 V64:$Rm)))))]>;
10480   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10481     [(set (v4i32 V128:$dst),
10482           (Accum (v4i32 V128:$Rd),
10483                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
10484                                                    (v4i32 V128:$Rm)))))]>;
10487 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10488                                      SDPatternOperator Accum> {
10489   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10490                                           V64, V64, V128_lo, VectorIndexH,
10491                                           asm, ".4h", ".4h", ".4h", ".h",
10492     [(set (v4i16 V64:$dst),
10493           (Accum (v4i16 V64:$Rd),
10494                  (v4i16 (int_aarch64_neon_sqrdmulh
10495                           (v4i16 V64:$Rn),
10496                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10497                                                     VectorIndexH:$idx))))))]> {
10498     bits<3> idx;
10499     let Inst{11} = idx{2};
10500     let Inst{21} = idx{1};
10501     let Inst{20} = idx{0};
10502   }
10504   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10505                                           V128, V128, V128_lo, VectorIndexH,
10506                                           asm, ".8h", ".8h", ".8h", ".h",
10507     [(set (v8i16 V128:$dst),
10508           (Accum (v8i16 V128:$Rd),
10509                  (v8i16 (int_aarch64_neon_sqrdmulh
10510                           (v8i16 V128:$Rn),
10511                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10512                                                    VectorIndexH:$idx))))))]> {
10513     bits<3> idx;
10514     let Inst{11} = idx{2};
10515     let Inst{21} = idx{1};
10516     let Inst{20} = idx{0};
10517   }
10519   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10520                                           V64, V64, V128, VectorIndexS,
10521                                           asm, ".2s", ".2s", ".2s", ".s",
10522     [(set (v2i32 V64:$dst),
10523         (Accum (v2i32 V64:$Rd),
10524                (v2i32 (int_aarch64_neon_sqrdmulh
10525                         (v2i32 V64:$Rn),
10526                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10527                                                  VectorIndexS:$idx))))))]> {
10528     bits<2> idx;
10529     let Inst{11} = idx{1};
10530     let Inst{21} = idx{0};
10531   }
10533   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10534   // an intermediate EXTRACT_SUBREG would be untyped.
10535   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
10536   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
10537   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10538                        (i32 (vector_extract
10539                                (v4i32 (insert_subvector
10540                                        (undef),
10541                                         (v2i32 (int_aarch64_neon_sqrdmulh
10542                                                  (v2i32 V64:$Rn),
10543                                                  (v2i32 (AArch64duplane32
10544                                                           (v4i32 V128:$Rm),
10545                                                           VectorIndexS:$idx)))),
10546                                       (i64 0))),
10547                                (i64 0))))),
10548             (EXTRACT_SUBREG
10549                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
10550                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
10551                                                 FPR32Op:$Rd,
10552                                                 ssub)),
10553                           V64:$Rn,
10554                           V128:$Rm,
10555                           VectorIndexS:$idx)),
10556                 ssub)>;
10558   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10559                                           V128, V128, V128, VectorIndexS,
10560                                           asm, ".4s", ".4s", ".4s", ".s",
10561     [(set (v4i32 V128:$dst),
10562           (Accum (v4i32 V128:$Rd),
10563                  (v4i32 (int_aarch64_neon_sqrdmulh
10564                           (v4i32 V128:$Rn),
10565                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10566                                                    VectorIndexS:$idx))))))]> {
10567     bits<2> idx;
10568     let Inst{11} = idx{1};
10569     let Inst{21} = idx{0};
10570   }
10572   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10573   // an intermediate EXTRACT_SUBREG would be untyped.
10574   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10575                         (i32 (vector_extract
10576                                (v4i32 (int_aarch64_neon_sqrdmulh
10577                                         (v4i32 V128:$Rn),
10578                                         (v4i32 (AArch64duplane32
10579                                                  (v4i32 V128:$Rm),
10580                                                  VectorIndexS:$idx)))),
10581                                (i64 0))))),
10582             (EXTRACT_SUBREG
10583                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
10584                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
10585                                                FPR32Op:$Rd,
10586                                                ssub)),
10587                          V128:$Rn,
10588                          V128:$Rm,
10589                          VectorIndexS:$idx)),
10590                 ssub)>;
10592   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10593                                         FPR16Op, FPR16Op, V128_lo,
10594                                         VectorIndexH, asm, ".h", "", "", ".h",
10595                                         []> {
10596     bits<3> idx;
10597     let Inst{11} = idx{2};
10598     let Inst{21} = idx{1};
10599     let Inst{20} = idx{0};
10600   }
10602   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10603                                         FPR32Op, FPR32Op, V128, VectorIndexS,
10604                                         asm, ".s", "", "", ".s",
10605     [(set (i32 FPR32Op:$dst),
10606           (Accum (i32 FPR32Op:$Rd),
10607                  (i32 (int_aarch64_neon_sqrdmulh
10608                         (i32 FPR32Op:$Rn),
10609                         (i32 (vector_extract (v4i32 V128:$Rm),
10610                                              VectorIndexS:$idx))))))]> {
10611     bits<2> idx;
10612     let Inst{11} = idx{1};
10613     let Inst{21} = idx{0};
10614   }
10616 } // let Predicates = [HasNeon, HasRDM]
10618 //----------------------------------------------------------------------------
10619 // ARMv8.3 Complex ADD/MLA instructions
10620 //----------------------------------------------------------------------------
10622 class ComplexRotationOperand<int Angle, int Remainder, string Type>
10623   : AsmOperandClass {
10624   let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10625   let DiagnosticType = "InvalidComplexRotation" # Type;
10626   let Name = "ComplexRotation" # Type;
10628 def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10629                                                   SDNodeXForm<imm, [{
10630   return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10631 }]>> {
10632   let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10633   let PrintMethod = "printComplexRotationOp<90, 0>";
10635 def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10636                                                   SDNodeXForm<imm, [{
10637   return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10638 }]>> {
10639   let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10640   let PrintMethod = "printComplexRotationOp<180, 90>";
10642 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10643 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10644                                      RegisterOperand regtype, Operand rottype,
10645                                      string asm, string kind, list<dag> pattern>
10646   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10647       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10648       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10649     Sched<[WriteV]> {
10650   bits<5> Rd;
10651   bits<5> Rn;
10652   bits<5> Rm;
10653   bits<1> rot;
10654   let Inst{31}    = 0;
10655   let Inst{30}    = Q;
10656   let Inst{29}    = U;
10657   let Inst{28-24} = 0b01110;
10658   let Inst{23-22} = size;
10659   let Inst{21}    = 0;
10660   let Inst{20-16} = Rm;
10661   let Inst{15-13} = opcode;
10662   // Non-tied version (FCADD) only has one rotation bit
10663   let Inst{12}    = rot;
10664   let Inst{11}    = 0;
10665   let Inst{10}    = 1;
10666   let Inst{9-5}   = Rn;
10667   let Inst{4-0}   = Rd;
10670 //8.3 CompNum - Floating-point complex number support
10671 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10672                                           string asm, SDPatternOperator OpNode>{
10673   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10674   def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10675               asm, ".4h",
10676               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10677                                               (v4f16 V64:$Rn),
10678                                               (v4f16 V64:$Rm),
10679                                               (i32 rottype:$rot)))]>;
10681   def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10682               asm, ".8h",
10683               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10684                                                (v8f16 V128:$Rn),
10685                                                (v8f16 V128:$Rm),
10686                                                (i32 rottype:$rot)))]>;
10687   }
10689   let Predicates = [HasComplxNum, HasNEON] in {
10690   def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10691               asm, ".2s",
10692               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10693                                               (v2f32 V64:$Rn),
10694                                               (v2f32 V64:$Rm),
10695                                               (i32 rottype:$rot)))]>;
10697   def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10698               asm, ".4s",
10699               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10700                                                (v4f32 V128:$Rn),
10701                                                (v4f32 V128:$Rm),
10702                                                (i32 rottype:$rot)))]>;
10704   def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10705               asm, ".2d",
10706               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10707                                                (v2f64 V128:$Rn),
10708                                                (v2f64 V128:$Rm),
10709                                                (i32 rottype:$rot)))]>;
10710   }
10713 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10714 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10715                                          bits<3> opcode,
10716                                          RegisterOperand regtype,
10717                                          Operand rottype, string asm,
10718                                          string kind, list<dag> pattern>
10719   : I<(outs regtype:$dst),
10720       (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10721       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10722       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10723     Sched<[WriteV]> {
10724   bits<5> Rd;
10725   bits<5> Rn;
10726   bits<5> Rm;
10727   bits<2> rot;
10728   let Inst{31}    = 0;
10729   let Inst{30}    = Q;
10730   let Inst{29}    = U;
10731   let Inst{28-24} = 0b01110;
10732   let Inst{23-22} = size;
10733   let Inst{21}    = 0;
10734   let Inst{20-16} = Rm;
10735   let Inst{15-13} = opcode;
10736   let Inst{12-11} = rot;
10737   let Inst{10}    = 1;
10738   let Inst{9-5}   = Rn;
10739   let Inst{4-0}   = Rd;
10742 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10743                                              Operand rottype, string asm,
10744                                              SDPatternOperator OpNode> {
10745   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10746   def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10747               rottype, asm, ".4h",
10748               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10749                                               (v4f16 V64:$Rn),
10750                                               (v4f16 V64:$Rm),
10751                                               (i32 rottype:$rot)))]>;
10753   def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10754               rottype, asm, ".8h",
10755               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10756                                                (v8f16 V128:$Rn),
10757                                                (v8f16 V128:$Rm),
10758                                                (i32 rottype:$rot)))]>;
10759   }
10761   let Predicates = [HasComplxNum, HasNEON] in {
10762   def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10763               rottype, asm, ".2s",
10764               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10765                                               (v2f32 V64:$Rn),
10766                                               (v2f32 V64:$Rm),
10767                                               (i32 rottype:$rot)))]>;
10769   def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10770               rottype, asm, ".4s",
10771               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10772                                                (v4f32 V128:$Rn),
10773                                                (v4f32 V128:$Rm),
10774                                                (i32 rottype:$rot)))]>;
10776   def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10777               rottype, asm, ".2d",
10778               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10779                                                (v2f64 V128:$Rn),
10780                                                (v2f64 V128:$Rm),
10781                                                (i32 rottype:$rot)))]>;
10782   }
10785 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10786 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10787                                  bit opc1, bit opc2, RegisterOperand dst_reg,
10788                                  RegisterOperand lhs_reg,
10789                                  RegisterOperand rhs_reg, Operand vec_idx,
10790                                  Operand rottype, string asm, string apple_kind,
10791                                  string dst_kind, string lhs_kind,
10792                                  string rhs_kind, list<dag> pattern>
10793   : I<(outs dst_reg:$dst),
10794       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10795       asm,
10796       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10797       "$idx, $rot" # "|" # apple_kind #
10798       "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10799     Sched<[WriteV]> {
10800   bits<5> Rd;
10801   bits<5> Rn;
10802   bits<5> Rm;
10803   bits<2> rot;
10805   let Inst{31}    = 0;
10806   let Inst{30}    = Q;
10807   let Inst{29}    = U;
10808   let Inst{28}    = Scalar;
10809   let Inst{27-24} = 0b1111;
10810   let Inst{23-22} = size;
10811   // Bit 21 must be set by the derived class.
10812   let Inst{20-16} = Rm;
10813   let Inst{15}    = opc1;
10814   let Inst{14-13} = rot;
10815   let Inst{12}    = opc2;
10816   // Bit 11 must be set by the derived class.
10817   let Inst{10}    = 0;
10818   let Inst{9-5}   = Rn;
10819   let Inst{4-0}   = Rd;
10822 // The complex instructions index by pairs of elements, so the VectorIndexes
10823 // don't match the lane types, and the index bits are different to the other
10824 // classes.
10825 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10826                                      string asm, SDPatternOperator OpNode> {
10827   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10828   def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10829                       V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10830                       ".4h", ".h", []> {
10831     bits<1> idx;
10832     let Inst{11} = 0;
10833     let Inst{21} = idx{0};
10834   }
10836   def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10837                       V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10838                       ".8h", ".8h", ".h", []> {
10839     bits<2> idx;
10840     let Inst{11} = idx{1};
10841     let Inst{21} = idx{0};
10842   }
10843   } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10845   let Predicates = [HasComplxNum, HasNEON] in {
10846   def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10847                       V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10848                       ".4s", ".4s", ".s", []> {
10849     bits<1> idx;
10850     let Inst{11} = idx{0};
10851     let Inst{21} = 0;
10852   }
10853   } // Predicates = [HasComplxNum, HasNEON]
10856 //----------------------------------------------------------------------------
10857 // Crypto extensions
10858 //----------------------------------------------------------------------------
10860 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10861 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10862               list<dag> pat>
10863   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10864     Sched<[WriteV]>{
10865   bits<5> Rd;
10866   bits<5> Rn;
10867   let Inst{31-16} = 0b0100111000101000;
10868   let Inst{15-12} = opc;
10869   let Inst{11-10} = 0b10;
10870   let Inst{9-5}   = Rn;
10871   let Inst{4-0}   = Rd;
10874 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10875   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10876             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10878 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10879   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10880             "$Rd = $dst",
10881             [(set (v16i8 V128:$dst),
10882                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10884 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10885 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10886                      dag oops, dag iops, list<dag> pat>
10887   : I<oops, iops, asm,
10888       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10889       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10890     Sched<[WriteV]>{
10891   bits<5> Rd;
10892   bits<5> Rn;
10893   bits<5> Rm;
10894   let Inst{31-21} = 0b01011110000;
10895   let Inst{20-16} = Rm;
10896   let Inst{15}    = 0;
10897   let Inst{14-12} = opc;
10898   let Inst{11-10} = 0b00;
10899   let Inst{9-5}   = Rn;
10900   let Inst{4-0}   = Rd;
10903 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10904   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10905                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10906                    [(set (v4i32 FPR128:$dst),
10907                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10908                                  (v4i32 V128:$Rm)))]>;
10910 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10911   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10912                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
10913                    [(set (v4i32 V128:$dst),
10914                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10915                                  (v4i32 V128:$Rm)))]>;
10917 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10918   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10919                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10920                    [(set (v4i32 FPR128:$dst),
10921                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10922                                  (v4i32 V128:$Rm)))]>;
10924 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10925 class SHA2OpInst<bits<4> opc, string asm, string kind,
10926                  string cstr, dag oops, dag iops,
10927                  list<dag> pat>
10928   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10929                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10930     Sched<[WriteV]>{
10931   bits<5> Rd;
10932   bits<5> Rn;
10933   let Inst{31-16} = 0b0101111000101000;
10934   let Inst{15-12} = opc;
10935   let Inst{11-10} = 0b10;
10936   let Inst{9-5}   = Rn;
10937   let Inst{4-0}   = Rd;
10940 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10941   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10942                (ins V128:$Rd, V128:$Rn),
10943                [(set (v4i32 V128:$dst),
10944                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10946 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10947   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10948                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10950 // Armv8.2-A Crypto extensions
10951 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10952                     list<dag> pattern>
10953   : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10954   bits<5> Vd;
10955   bits<5> Vn;
10956   let Inst{31-25} = 0b1100111;
10957   let Inst{9-5}   = Vn;
10958   let Inst{4-0}   = Vd;
10961 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10962   : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
10963                   "$Vd = $Vdst", []> {
10964   let Inst{31-25} = 0b1100111;
10965   let Inst{24-21} = 0b0110;
10966   let Inst{20-15} = 0b000001;
10967   let Inst{14}    = op0;
10968   let Inst{13-12} = 0b00;
10969   let Inst{11-10} = op1;
10971 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10972   : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
10973 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10974   : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
10976 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10977                 string asmops, string cst>
10978   : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10979   bits<5> Vm;
10980   let Inst{24-21} = 0b0011;
10981   let Inst{20-16} = Vm;
10982   let Inst{15}    = 0b1;
10983   let Inst{14}    = op0;
10984   let Inst{13-12} = 0b00;
10985   let Inst{11-10} = op1;
10987 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10988   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10989               "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
10990 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10991   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10992               "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10993 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10994   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10995               "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
10996 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10997   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10998               "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10999 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11000   : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11001               asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11003 class CryptoRRRR<bits<2>op0, string asm, string asmops>
11004   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11005                   asmops, "", []> {
11006   bits<5> Vm;
11007   bits<5> Va;
11008   let Inst{24-23} = 0b00;
11009   let Inst{22-21} = op0;
11010   let Inst{20-16} = Vm;
11011   let Inst{15}    = 0b0;
11012   let Inst{14-10} = Va;
11014 class CryptoRRRR_16B<bits<2>op0, string asm>
11015  : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11016                         "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11018 class CryptoRRRR_4S<bits<2>op0, string asm>
11019  : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11020                          "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11023 class CryptoRRRi6<string asm>
11024   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11025                   "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11026                   "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11027   bits<6> imm;
11028   bits<5> Vm;
11029   let Inst{24-21} = 0b0100;
11030   let Inst{20-16} = Vm;
11031   let Inst{15-10} = imm;
11032   let Inst{9-5}   = Vn;
11033   let Inst{4-0}   = Vd;
11036 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11037   : BaseCryptoV82<(outs V128:$Vdst),
11038                   (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11039                   asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11040                        "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11041   bits<2> imm;
11042   bits<5> Vm;
11043   let Inst{24-21} = 0b0010;
11044   let Inst{20-16} = Vm;
11045   let Inst{15}    = 0b1;
11046   let Inst{14}    = op0;
11047   let Inst{13-12} = imm;
11048   let Inst{11-10} = op1;
11051 //----------------------------------------------------------------------------
11052 // v8.1 atomic instructions extension:
11053 // * CAS
11054 // * CASP
11055 // * SWP
11056 // * LDOPregister<OP>, and aliases STOPregister<OP>
11058 // Instruction encodings:
11060 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11061 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11062 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11063 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11064 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11065 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11067 // Instruction syntax:
11069 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11070 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11071 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11072 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11073 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11074 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11075 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11076 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11077 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11078 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
11080 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11081 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11082                       string cstr, list<dag> pattern>
11083       : I<oops, iops, asm, operands, cstr, pattern> {
11084   bits<2> Sz;
11085   bit NP;
11086   bit Acq;
11087   bit Rel;
11088   bits<5> Rs;
11089   bits<5> Rn;
11090   bits<5> Rt;
11091   let Inst{31-30} = Sz;
11092   let Inst{29-24} = 0b001000;
11093   let Inst{23} = NP;
11094   let Inst{22} = Acq;
11095   let Inst{21} = 0b1;
11096   let Inst{20-16} = Rs;
11097   let Inst{15} = Rel;
11098   let Inst{14-10} = 0b11111;
11099   let Inst{9-5} = Rn;
11100   let Inst{4-0} = Rt;
11101   let Predicates = [HasLSE];
11104 class BaseCAS<string order, string size, RegisterClass RC>
11105       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11106                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11107                         "$out = $Rs",[]>,
11108         Sched<[WriteAtomic]> {
11109   let NP = 1;
11112 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11113   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11114   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11115   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11116   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11119 class BaseCASP<string order, string size, RegisterOperand RC>
11120       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11121                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11122                         "$out = $Rs",[]>,
11123         Sched<[WriteAtomic]> {
11124   let NP = 0;
11127 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11128   let Sz = 0b00, Acq = Acq, Rel = Rel in
11129     def W : BaseCASP<order, "", WSeqPairClassOperand>;
11130   let Sz = 0b01, Acq = Acq, Rel = Rel in
11131     def X : BaseCASP<order, "", XSeqPairClassOperand>;
11134 let Predicates = [HasLSE] in
11135 class BaseSWP<string order, string size, RegisterClass RC>
11136       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11137           "\t$Rs, $Rt, [$Rn]","",[]>,
11138         Sched<[WriteAtomic]> {
11139   bits<2> Sz;
11140   bit Acq;
11141   bit Rel;
11142   bits<5> Rs;
11143   bits<3> opc = 0b000;
11144   bits<5> Rn;
11145   bits<5> Rt;
11146   let Inst{31-30} = Sz;
11147   let Inst{29-24} = 0b111000;
11148   let Inst{23} = Acq;
11149   let Inst{22} = Rel;
11150   let Inst{21} = 0b1;
11151   let Inst{20-16} = Rs;
11152   let Inst{15} = 0b1;
11153   let Inst{14-12} = opc;
11154   let Inst{11-10} = 0b00;
11155   let Inst{9-5} = Rn;
11156   let Inst{4-0} = Rt;
11157   let Predicates = [HasLSE];
11160 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11161   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11162   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11163   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11164   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11167 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11168 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11169       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11170           "\t$Rs, $Rt, [$Rn]","",[]>,
11171         Sched<[WriteAtomic]> {
11172   bits<2> Sz;
11173   bit Acq;
11174   bit Rel;
11175   bits<5> Rs;
11176   bits<3> opc;
11177   bits<5> Rn;
11178   bits<5> Rt;
11179   let Inst{31-30} = Sz;
11180   let Inst{29-24} = 0b111000;
11181   let Inst{23} = Acq;
11182   let Inst{22} = Rel;
11183   let Inst{21} = 0b1;
11184   let Inst{20-16} = Rs;
11185   let Inst{15} = 0b0;
11186   let Inst{14-12} = opc;
11187   let Inst{11-10} = 0b00;
11188   let Inst{9-5} = Rn;
11189   let Inst{4-0} = Rt;
11190   let Predicates = [HasLSE];
11193 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11194                         string order> {
11195   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11196     def B : BaseLDOPregister<op, order, "b", GPR32>;
11197   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11198     def H : BaseLDOPregister<op, order, "h", GPR32>;
11199   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11200     def W : BaseLDOPregister<op, order, "", GPR32>;
11201   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11202     def X : BaseLDOPregister<op, order, "", GPR64>;
11205 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11206 // complex DAG for DstRHS.
11207 let Predicates = [HasLSE] in
11208 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11209                                          string size, dag SrcRHS, dag DstRHS> {
11210   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11211             (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11212   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11213             (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11214   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11215             (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11216   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11217             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11218   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11219             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11222 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11223                                      string size, dag RHS> {
11224   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11227 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11228                                          string size, dag LHS, dag RHS> {
11229   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11232 multiclass LDOPregister_patterns<string inst, string op> {
11233   defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11234   defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11235   defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11236   defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11239 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11240   defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11241                         (i64 GPR64:$Rm),
11242                         (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11243   defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11244                         (i32 GPR32:$Rm),
11245                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11246   defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11247                         (i32 GPR32:$Rm),
11248                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11249   defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11250                         (i32 GPR32:$Rm),
11251                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11254 let Predicates = [HasLSE] in
11255 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11256                                         string size, dag OLD, dag NEW> {
11257   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11258             (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11259   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11260             (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11261   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11262             (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11263   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11264             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11265   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11266             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11269 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11270                                     string size, dag OLD, dag NEW> {
11271   defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11274 multiclass CASregister_patterns<string inst, string op> {
11275   defm : CASregister_patterns_ord<inst, "X", op, "64",
11276                         (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11277   defm : CASregister_patterns_ord<inst, "W", op, "32",
11278                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11279   defm : CASregister_patterns_ord<inst, "H", op, "16",
11280                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11281   defm : CASregister_patterns_ord<inst, "B", op, "8",
11282                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11285 let Predicates = [HasLSE] in
11286 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11287                         Instruction inst> :
11288       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11290 multiclass STOPregister<string asm, string instr> {
11291   def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11292                     !cast<Instruction>(instr # "LB")>;
11293   def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11294                     !cast<Instruction>(instr # "LH")>;
11295   def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11296                     !cast<Instruction>(instr # "LW")>;
11297   def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11298                     !cast<Instruction>(instr # "LX")>;
11299   def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11300                     !cast<Instruction>(instr # "B")>;
11301   def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11302                     !cast<Instruction>(instr # "H")>;
11303   def : BaseSTOPregister<asm,        GPR32, WZR,
11304                     !cast<Instruction>(instr # "W")>;
11305   def : BaseSTOPregister<asm,        GPR64, XZR,
11306                     !cast<Instruction>(instr # "X")>;
11309 class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11310                         dag iops, dag oops, list<dag> pat>
11311     : I<oops, iops, asm_inst, asm_ops, "", pat>,
11312       Sched<[]> /* FIXME: fill in scheduling details once known */ {
11313   bits<5> Rt;
11314   bits<5> Rn;
11315   let Inst{31-21} = 0b11111000001;
11316   let Inst{15}    = 1;
11317   let Inst{14-12} = opc;
11318   let Inst{11-10} = 0b00;
11319   let Inst{9-5}   = Rn;
11320   let Inst{4-0}   = Rt;
11322   let Predicates = [HasV8_7a];
11325 class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11326                       list<dag> pat = []>
11327     : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11328   let Inst{20-16} = 0b11111;
11331 class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11332     : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11333                        (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11334   bits<5> Rs;
11335   let Inst{20-16} = Rs;
11338 //----------------------------------------------------------------------------
11339 // Allow the size specifier tokens to be upper case, not just lower.
11340 def : TokenAlias<".4B", ".4b">;  // Add dot product
11341 def : TokenAlias<".8B", ".8b">;
11342 def : TokenAlias<".4H", ".4h">;
11343 def : TokenAlias<".2S", ".2s">;
11344 def : TokenAlias<".1D", ".1d">;
11345 def : TokenAlias<".16B", ".16b">;
11346 def : TokenAlias<".8H", ".8h">;
11347 def : TokenAlias<".4S", ".4s">;
11348 def : TokenAlias<".2D", ".2d">;
11349 def : TokenAlias<".1Q", ".1q">;
11350 def : TokenAlias<".2H", ".2h">;
11351 def : TokenAlias<".B", ".b">;
11352 def : TokenAlias<".H", ".h">;
11353 def : TokenAlias<".S", ".s">;
11354 def : TokenAlias<".D", ".d">;
11355 def : TokenAlias<".Q", ".q">;