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//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10//  Describe AArch64 instructions format here
11//
12
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.
16class Format<bits<2> val> {
17  bits<2> Value = val;
18}
19
20def PseudoFrm   : Format<0>;
21def NormalFrm   : Format<1>; // Do we need any others?
22
23// Enum describing whether an instruction is
24// destructive in its first source operand.
25class DestructiveInstTypeEnum<bits<4> val> {
26  bits<4> Value = val;
27}
28def NotDestructive                : DestructiveInstTypeEnum<0>;
29// Destructive in its first operand and can be MOVPRFX'd, but has no other
30// special properties.
31def DestructiveOther              : DestructiveInstTypeEnum<1>;
32def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39def DestructiveUnaryPassthru      : DestructiveInstTypeEnum<9>;
40
41class FalseLanesEnum<bits<2> val> {
42  bits<2> Value = val;
43}
44def FalseLanesNone  : FalseLanesEnum<0>;
45def FalseLanesZero  : FalseLanesEnum<1>;
46def FalseLanesUndef : FalseLanesEnum<2>;
47
48class SMEMatrixTypeEnum<bits<3> val> {
49  bits<3> Value = val;
50}
51def SMEMatrixNone  : SMEMatrixTypeEnum<0>;
52def SMEMatrixTileB : SMEMatrixTypeEnum<1>;
53def SMEMatrixTileH : SMEMatrixTypeEnum<2>;
54def SMEMatrixTileS : SMEMatrixTypeEnum<3>;
55def SMEMatrixTileD : SMEMatrixTypeEnum<4>;
56def SMEMatrixTileQ : SMEMatrixTypeEnum<5>;
57def SMEMatrixArray : SMEMatrixTypeEnum<6>;
58
59// AArch64 Instruction Format
60class AArch64Inst<Format f, string cstr> : Instruction {
61  field bits<32> Inst; // Instruction encoding.
62  // Mask of bits that cause an encoding to be UNPREDICTABLE.
63  // If a bit is set, then if the corresponding bit in the
64  // target encoding differs from its value in the "Inst" field,
65  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
66  field bits<32> Unpredictable = 0;
67  // SoftFail is the generic name for this field, but we alias it so
68  // as to make it more obvious what it means in ARM-land.
69  field bits<32> SoftFail = Unpredictable;
70  let Namespace   = "AArch64";
71  Format F        = f;
72  bits<2> Form    = F.Value;
73
74  // Defaults
75  bit isWhile = 0;
76  bit isPTestLike = 0;
77  FalseLanesEnum FalseLanes = FalseLanesNone;
78  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
79  SMEMatrixTypeEnum SMEMatrixType = SMEMatrixNone;
80  ElementSizeEnum ElementSize = ElementSizeNone;
81
82  let TSFlags{13-11} = SMEMatrixType.Value;
83  let TSFlags{10}    = isPTestLike;
84  let TSFlags{9}     = isWhile;
85  let TSFlags{8-7}   = FalseLanes.Value;
86  let TSFlags{6-3}   = DestructiveInstType.Value;
87  let TSFlags{2-0}   = ElementSize.Value;
88
89  let Pattern       = [];
90  let Constraints   = cstr;
91}
92
93class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
94  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
95
96// Pseudo instructions (don't have encoding information)
97class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
98    : AArch64Inst<PseudoFrm, cstr> {
99  dag OutOperandList = oops;
100  dag InOperandList  = iops;
101  let Pattern        = pattern;
102  let isCodeGenOnly  = 1;
103  let isPseudo       = 1;
104}
105
106// Real instructions (have encoding information)
107class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
108  let Pattern = pattern;
109  let Size = 4;
110}
111
112// Normal instructions
113class I<dag oops, dag iops, string asm, string operands, string cstr,
114        list<dag> pattern>
115    : EncodedI<cstr, pattern> {
116  dag OutOperandList = oops;
117  dag InOperandList  = iops;
118  let AsmString      = !strconcat(asm, operands);
119}
120
121class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
122class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
123class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
124
125// Helper fragment for an extract of the high portion of a 128-bit vector. The
126// ComplexPattern match both extract_subvector and bitcast(extract_subvector(..)).
127def extract_high_v16i8 :
128    ComplexPattern<v8i8, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
129def extract_high_v8i16 :
130    ComplexPattern<v4i16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
131def extract_high_v4i32 :
132    ComplexPattern<v2i32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
133def extract_high_v2i64 :
134    ComplexPattern<v1i64, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
135
136def gi_extract_high_v16i8 :
137  GIComplexOperandMatcher<v8s8, "selectExtractHigh">,
138  GIComplexPatternEquiv<extract_high_v16i8>;
139def gi_extract_high_v8i16 :
140  GIComplexOperandMatcher<v4s16, "selectExtractHigh">,
141  GIComplexPatternEquiv<extract_high_v8i16>;
142def gi_extract_high_v4i32 :
143  GIComplexOperandMatcher<v2s32, "selectExtractHigh">,
144  GIComplexPatternEquiv<extract_high_v4i32>;
145
146def extract_high_v8f16 :
147    ComplexPattern<v4f16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
148def extract_high_v4f32 :
149    ComplexPattern<v2f32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
150
151def gi_extract_high_v8f16 :
152  GIComplexOperandMatcher<v4s16, "selectExtractHigh">,
153  GIComplexPatternEquiv<extract_high_v8f16>;
154def gi_extract_high_v4f32 :
155  GIComplexOperandMatcher<v2s32, "selectExtractHigh">,
156  GIComplexPatternEquiv<extract_high_v4f32>;
157
158def extract_high_dup_v8i16 :
159   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
160def extract_high_dup_v4i32 :
161   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
162
163def dup_v8i16 :
164    PatFrags<(ops node:$LHS, node:$RHS),
165             [(v4i16 (extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 0))),
166              (v4i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS))]>;
167def dup_v4i32 :
168    PatFrags<(ops node:$LHS, node:$RHS),
169             [(v2i32 (extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 0))),
170              (v2i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS))]>;
171def dup_v8f16 :
172    PatFrags<(ops node:$LHS, node:$RHS),
173             [(v4f16 (extract_subvector (v8f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS)), (i64 0))),
174              (v4f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS))]>;
175def dup_v4f32 :
176    PatFrags<(ops node:$LHS, node:$RHS),
177             [(v2f32 (extract_subvector (v4f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS)), (i64 0))),
178              (v2f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS))]>;
179
180//===----------------------------------------------------------------------===//
181// Asm Operand Classes.
182//
183
184// Shifter operand for arithmetic shifted encodings.
185def ShifterOperand : AsmOperandClass {
186  let Name = "Shifter";
187}
188
189// Shifter operand for mov immediate encodings.
190def MovImm32ShifterOperand : AsmOperandClass {
191  let SuperClasses = [ShifterOperand];
192  let Name = "MovImm32Shifter";
193  let RenderMethod = "addShifterOperands";
194  let DiagnosticType = "InvalidMovImm32Shift";
195}
196def MovImm64ShifterOperand : AsmOperandClass {
197  let SuperClasses = [ShifterOperand];
198  let Name = "MovImm64Shifter";
199  let RenderMethod = "addShifterOperands";
200  let DiagnosticType = "InvalidMovImm64Shift";
201}
202
203// Shifter operand for arithmetic register shifted encodings.
204class ArithmeticShifterOperand<int width> : AsmOperandClass {
205  let SuperClasses = [ShifterOperand];
206  let Name = "ArithmeticShifter" # width;
207  let PredicateMethod = "isArithmeticShifter<" # width # ">";
208  let RenderMethod = "addShifterOperands";
209  let DiagnosticType = "AddSubRegShift" # width;
210}
211
212def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
213def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
214
215// Shifter operand for logical register shifted encodings.
216class LogicalShifterOperand<int width> : AsmOperandClass {
217  let SuperClasses = [ShifterOperand];
218  let Name = "LogicalShifter" # width;
219  let PredicateMethod = "isLogicalShifter<" # width # ">";
220  let RenderMethod = "addShifterOperands";
221  let DiagnosticType = "AddSubRegShift" # width;
222}
223
224def LogicalShifterOperand32 : LogicalShifterOperand<32>;
225def LogicalShifterOperand64 : LogicalShifterOperand<64>;
226
227// Shifter operand for logical vector 128/64-bit shifted encodings.
228def LogicalVecShifterOperand : AsmOperandClass {
229  let SuperClasses = [ShifterOperand];
230  let Name = "LogicalVecShifter";
231  let RenderMethod = "addShifterOperands";
232}
233def LogicalVecHalfWordShifterOperand : AsmOperandClass {
234  let SuperClasses = [LogicalVecShifterOperand];
235  let Name = "LogicalVecHalfWordShifter";
236  let RenderMethod = "addShifterOperands";
237}
238
239// The "MSL" shifter on the vector MOVI instruction.
240def MoveVecShifterOperand : AsmOperandClass {
241  let SuperClasses = [ShifterOperand];
242  let Name = "MoveVecShifter";
243  let RenderMethod = "addShifterOperands";
244}
245
246// Extend operand for arithmetic encodings.
247def ExtendOperand : AsmOperandClass {
248  let Name = "Extend";
249  let DiagnosticType = "AddSubRegExtendLarge";
250}
251def ExtendOperand64 : AsmOperandClass {
252  let SuperClasses = [ExtendOperand];
253  let Name = "Extend64";
254  let DiagnosticType = "AddSubRegExtendSmall";
255}
256// 'extend' that's a lsl of a 64-bit register.
257def ExtendOperandLSL64 : AsmOperandClass {
258  let SuperClasses = [ExtendOperand];
259  let Name = "ExtendLSL64";
260  let RenderMethod = "addExtend64Operands";
261  let DiagnosticType = "AddSubRegExtendLarge";
262}
263
264// 8-bit floating-point immediate encodings.
265def FPImmOperand : AsmOperandClass {
266  let Name = "FPImm";
267  let ParserMethod = "tryParseFPImm<true>";
268  let DiagnosticType = "InvalidFPImm";
269}
270
271def CondCode : AsmOperandClass {
272  let Name = "CondCode";
273  let DiagnosticType = "InvalidCondCode";
274}
275
276// A 32-bit register pasrsed as 64-bit
277def GPR32as64Operand : AsmOperandClass {
278  let Name = "GPR32as64";
279  let ParserMethod =
280      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
281}
282def GPR32as64 : RegisterOperand<GPR32> {
283  let ParserMatchClass = GPR32as64Operand;
284}
285
286// A 64-bit register pasrsed as 32-bit
287def GPR64as32Operand : AsmOperandClass {
288  let Name = "GPR64as32";
289  let ParserMethod =
290      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
291}
292def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
293  let ParserMatchClass = GPR64as32Operand;
294}
295
296// 8-bit immediate for AdvSIMD where 64-bit values of the form:
297// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
298// are encoded as the eight bit value 'abcdefgh'.
299def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
300
301class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
302  let Name = "UImm" # Width # "s" # Scale;
303  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
304  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
305  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
306}
307
308class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
309  let Name = "SImm" # Width # "s" # Scale;
310  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
311  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
312  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
313}
314
315//===----------------------------------------------------------------------===//
316// Operand Definitions.
317//
318
319// ADR[P] instruction labels.
320def AdrpOperand : AsmOperandClass {
321  let Name = "AdrpLabel";
322  let ParserMethod = "tryParseAdrpLabel";
323  let DiagnosticType = "InvalidLabel";
324}
325def adrplabel : Operand<i64> {
326  let EncoderMethod = "getAdrLabelOpValue";
327  let PrintMethod = "printAdrAdrpLabel";
328  let ParserMatchClass = AdrpOperand;
329  let OperandType = "OPERAND_PCREL";
330}
331
332def AdrOperand : AsmOperandClass {
333  let Name = "AdrLabel";
334  let ParserMethod = "tryParseAdrLabel";
335  let DiagnosticType = "InvalidLabel";
336}
337def adrlabel : Operand<i64> {
338  let EncoderMethod = "getAdrLabelOpValue";
339  let PrintMethod = "printAdrAdrpLabel";
340  let ParserMatchClass = AdrOperand;
341  let OperandType = "OPERAND_PCREL";
342}
343
344class SImmOperand<int width> : AsmOperandClass {
345  let Name = "SImm" # width;
346  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
347  let RenderMethod = "addImmOperands";
348  let PredicateMethod = "isSImm<" # width # ">";
349}
350
351class AsmImmRange<int Low, int High> : AsmOperandClass {
352  let Name = "Imm" # Low # "_" # High;
353  let DiagnosticType = "InvalidImm" # Low # "_" # High;
354  let RenderMethod = "addImmOperands";
355  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
356}
357
358// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
359def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
360def simm10Scaled : Operand<i64> {
361  let ParserMatchClass = SImm10s8Operand;
362  let DecoderMethod = "DecodeSImm<10>";
363  let PrintMethod = "printImmScale<8>";
364}
365
366def simm9s16 : Operand<i64> {
367  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
368  let DecoderMethod = "DecodeSImm<9>";
369  let PrintMethod = "printImmScale<16>";
370}
371
372// uimm6 predicate - True if the immediate is in the range [0, 63].
373def UImm6Operand : AsmOperandClass {
374  let Name = "UImm6";
375  let DiagnosticType = "InvalidImm0_63";
376}
377
378def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
379  let ParserMatchClass = UImm6Operand;
380}
381
382def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
383  let ParserMatchClass = AsmImmRange<0, 65535>;
384}
385
386def SImm9Operand : SImmOperand<9>;
387def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
388  let ParserMatchClass = SImm9Operand;
389  let DecoderMethod = "DecodeSImm<9>";
390}
391
392// imm0_255 predicate - True if the immediate is in the range [0,255].
393def Imm0_255Operand : AsmImmRange<0,255>;
394
395def uimm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
396  let ParserMatchClass = Imm0_255Operand;
397}
398def uimm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
399  let ParserMatchClass = Imm0_255Operand;
400}
401
402def SImm8Operand : SImmOperand<8>;
403def simm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
404  let ParserMatchClass = SImm8Operand;
405  let DecoderMethod = "DecodeSImm<8>";
406}
407def simm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 128; }]> {
408  let ParserMatchClass = SImm8Operand;
409  let DecoderMethod = "DecodeSImm<8>";
410}
411
412def SImm6Operand : SImmOperand<6>;
413def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
414  let ParserMatchClass = SImm6Operand;
415  let DecoderMethod = "DecodeSImm<6>";
416}
417
418def SImm5Operand : SImmOperand<5>;
419def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
420  let ParserMatchClass = SImm5Operand;
421  let DecoderMethod = "DecodeSImm<5>";
422}
423
424def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
425  let ParserMatchClass = SImm5Operand;
426  let DecoderMethod = "DecodeSImm<5>";
427}
428
429def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
430  let ParserMatchClass = SImm5Operand;
431  let DecoderMethod = "DecodeSImm<5>";
432  let PrintMethod = "printSImm<8>";
433}
434
435def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
436  let ParserMatchClass = SImm5Operand;
437  let DecoderMethod = "DecodeSImm<5>";
438  let PrintMethod = "printSImm<16>";
439}
440
441// simm7sN predicate - True if the immediate is a multiple of N in the range
442// [-64 * N, 63 * N].
443
444def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
445def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
446def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
447
448def simm7s4 : Operand<i32> {
449  let ParserMatchClass = SImm7s4Operand;
450  let PrintMethod = "printImmScale<4>";
451}
452
453def simm7s8 : Operand<i32> {
454  let ParserMatchClass = SImm7s8Operand;
455  let PrintMethod = "printImmScale<8>";
456}
457
458def simm7s16 : Operand<i32> {
459  let ParserMatchClass = SImm7s16Operand;
460  let PrintMethod = "printImmScale<16>";
461}
462
463def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
464
465def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
466def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
467def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
468def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
469def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
470
471def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
472def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
473
474def UImmS1XForm : SDNodeXForm<imm, [{
475  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
476}]>;
477def UImmS2XForm : SDNodeXForm<imm, [{
478  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
479}]>;
480def UImmS4XForm : SDNodeXForm<imm, [{
481  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
482}]>;
483def UImmS8XForm : SDNodeXForm<imm, [{
484  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
485}]>;
486
487// uimm5sN predicate - True if the immediate is a multiple of N in the range
488// [0 * N, 32 * N].
489def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
490def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
491def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
492
493def uimm5s2 : Operand<i64>, ImmLeaf<i64,
494                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
495                UImmS2XForm> {
496  let ParserMatchClass = UImm5s2Operand;
497  let PrintMethod = "printImmScale<2>";
498}
499def uimm5s4 : Operand<i64>, ImmLeaf<i64,
500                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
501                UImmS4XForm> {
502  let ParserMatchClass = UImm5s4Operand;
503  let PrintMethod = "printImmScale<4>";
504}
505def uimm5s8 : Operand<i64>, ImmLeaf<i64,
506                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
507                UImmS8XForm> {
508  let ParserMatchClass = UImm5s8Operand;
509  let PrintMethod = "printImmScale<8>";
510}
511
512// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
513// instead of ImmLeaf (Constant)
514def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
515                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
516                UImmS2XForm> {
517  let ParserMatchClass = UImm5s2Operand;
518  let PrintMethod = "printImmScale<2>";
519}
520def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
521                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
522                UImmS4XForm> {
523  let ParserMatchClass = UImm5s4Operand;
524  let PrintMethod = "printImmScale<4>";
525}
526def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
527                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
528                UImmS8XForm> {
529  let ParserMatchClass = UImm5s8Operand;
530  let PrintMethod = "printImmScale<8>";
531}
532
533// uimm6sN predicate - True if the immediate is a multiple of N in the range
534// [0 * N, 64 * N].
535def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
536def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
537def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
538def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
539def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
540
541def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
542  let ParserMatchClass = UImm6s1Operand;
543}
544def uimm6s2 : Operand<i64>, ImmLeaf<i64,
545[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
546  let PrintMethod = "printImmScale<2>";
547  let ParserMatchClass = UImm6s2Operand;
548}
549def uimm6s4 : Operand<i64>, ImmLeaf<i64,
550[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
551  let PrintMethod = "printImmScale<4>";
552  let ParserMatchClass = UImm6s4Operand;
553}
554def uimm6s8 : Operand<i64>, ImmLeaf<i64,
555[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
556  let PrintMethod = "printImmScale<8>";
557  let ParserMatchClass = UImm6s8Operand;
558}
559def uimm6s16 : Operand<i64>, ImmLeaf<i64,
560[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
561  let PrintMethod = "printImmScale<16>";
562  let ParserMatchClass = UImm6s16Operand;
563}
564
565def SImmS2XForm : SDNodeXForm<imm, [{
566  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
567}]>;
568def SImmS3XForm : SDNodeXForm<imm, [{
569  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
570}]>;
571def SImmS4XForm : SDNodeXForm<imm, [{
572  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
573}]>;
574def SImmS16XForm : SDNodeXForm<imm, [{
575  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
576}]>;
577def SImmS32XForm : SDNodeXForm<imm, [{
578  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
579}]>;
580
581// simm6sN predicate - True if the immediate is a multiple of N in the range
582// [-32 * N, 31 * N].
583def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
584def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
585  let ParserMatchClass = SImm6s1Operand;
586  let DecoderMethod = "DecodeSImm<6>";
587}
588
589// simm4sN predicate - True if the immediate is a multiple of N in the range
590// [ -8* N, 7 * N].
591def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
592def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
593def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
594def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
595def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
596def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
597
598def simm4s1 : Operand<i64>, ImmLeaf<i64,
599[{ return Imm >=-8  && Imm <= 7; }]> {
600  let ParserMatchClass = SImm4s1Operand;
601  let DecoderMethod = "DecodeSImm<4>";
602}
603
604def simm4s2 : Operand<i64>, ImmLeaf<i64,
605[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
606  let PrintMethod = "printImmScale<2>";
607  let ParserMatchClass = SImm4s2Operand;
608  let DecoderMethod = "DecodeSImm<4>";
609}
610
611def simm4s3 : Operand<i64>, ImmLeaf<i64,
612[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
613  let PrintMethod = "printImmScale<3>";
614  let ParserMatchClass = SImm4s3Operand;
615  let DecoderMethod = "DecodeSImm<4>";
616}
617
618def simm4s4 : Operand<i64>, ImmLeaf<i64,
619[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
620  let PrintMethod = "printImmScale<4>";
621  let ParserMatchClass = SImm4s4Operand;
622  let DecoderMethod = "DecodeSImm<4>";
623}
624def simm4s16 : Operand<i64>, ImmLeaf<i64,
625[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
626  let PrintMethod = "printImmScale<16>";
627  let ParserMatchClass = SImm4s16Operand;
628  let DecoderMethod = "DecodeSImm<4>";
629}
630def simm4s32 : Operand<i64>, ImmLeaf<i64,
631[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
632  let PrintMethod = "printImmScale<32>";
633  let ParserMatchClass = SImm4s32Operand;
634  let DecoderMethod = "DecodeSImm<4>";
635}
636
637def Imm1_8Operand : AsmImmRange<1, 8>;
638def Imm1_16Operand : AsmImmRange<1, 16>;
639def Imm1_32Operand : AsmImmRange<1, 32>;
640def Imm1_64Operand : AsmImmRange<1, 64>;
641
642class BranchTarget<int N> : AsmOperandClass {
643  let Name = "BranchTarget" # N;
644  let DiagnosticType = "InvalidLabel";
645  let PredicateMethod = "isBranchTarget<" # N # ">";
646}
647
648class PCRelLabel<int N> : BranchTarget<N> {
649  let Name = "PCRelLabel" # N;
650}
651
652def BranchTarget14Operand : BranchTarget<14>;
653def BranchTarget26Operand : BranchTarget<26>;
654def PCRelLabel19Operand   : PCRelLabel<19>;
655
656def MovWSymbolG3AsmOperand : AsmOperandClass {
657  let Name = "MovWSymbolG3";
658  let RenderMethod = "addImmOperands";
659}
660
661def movw_symbol_g3 : Operand<i32> {
662  let ParserMatchClass = MovWSymbolG3AsmOperand;
663}
664
665def MovWSymbolG2AsmOperand : AsmOperandClass {
666  let Name = "MovWSymbolG2";
667  let RenderMethod = "addImmOperands";
668}
669
670def movw_symbol_g2 : Operand<i32> {
671  let ParserMatchClass = MovWSymbolG2AsmOperand;
672}
673
674def MovWSymbolG1AsmOperand : AsmOperandClass {
675  let Name = "MovWSymbolG1";
676  let RenderMethod = "addImmOperands";
677}
678
679def movw_symbol_g1 : Operand<i32> {
680  let ParserMatchClass = MovWSymbolG1AsmOperand;
681}
682
683def MovWSymbolG0AsmOperand : AsmOperandClass {
684  let Name = "MovWSymbolG0";
685  let RenderMethod = "addImmOperands";
686}
687
688def movw_symbol_g0 : Operand<i32> {
689  let ParserMatchClass = MovWSymbolG0AsmOperand;
690}
691
692class fixedpoint_i32<ValueType FloatVT>
693  : Operand<FloatVT>,
694    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
695  let EncoderMethod = "getFixedPointScaleOpValue";
696  let DecoderMethod = "DecodeFixedPointScaleImm32";
697  let ParserMatchClass = Imm1_32Operand;
698}
699
700class fixedpoint_i64<ValueType FloatVT>
701  : Operand<FloatVT>,
702    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
703  let EncoderMethod = "getFixedPointScaleOpValue";
704  let DecoderMethod = "DecodeFixedPointScaleImm64";
705  let ParserMatchClass = Imm1_64Operand;
706}
707
708def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
709def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
710def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
711
712def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
713def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
714def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
715
716class fixedpoint_recip_i32<ValueType FloatVT>
717  : Operand<FloatVT>,
718    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<32>", [fpimm, ld]> {
719  let EncoderMethod = "getFixedPointScaleOpValue";
720  let DecoderMethod = "DecodeFixedPointScaleImm32";
721}
722
723class fixedpoint_recip_i64<ValueType FloatVT>
724  : Operand<FloatVT>,
725    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<64>", [fpimm, ld]> {
726  let EncoderMethod = "getFixedPointScaleOpValue";
727  let DecoderMethod = "DecodeFixedPointScaleImm64";
728}
729
730def fixedpoint_recip_f16_i32 : fixedpoint_recip_i32<f16>;
731def fixedpoint_recip_f32_i32 : fixedpoint_recip_i32<f32>;
732def fixedpoint_recip_f64_i32 : fixedpoint_recip_i32<f64>;
733
734def fixedpoint_recip_f16_i64 : fixedpoint_recip_i64<f16>;
735def fixedpoint_recip_f32_i64 : fixedpoint_recip_i64<f32>;
736def fixedpoint_recip_f64_i64 : fixedpoint_recip_i64<f64>;
737
738def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
739  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
740}]> {
741  let EncoderMethod = "getVecShiftR8OpValue";
742  let DecoderMethod = "DecodeVecShiftR8Imm";
743  let ParserMatchClass = Imm1_8Operand;
744}
745def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
746  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
747}]> {
748  let EncoderMethod = "getVecShiftR16OpValue";
749  let DecoderMethod = "DecodeVecShiftR16Imm";
750  let ParserMatchClass = Imm1_16Operand;
751}
752def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
753  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
754}]> {
755  let EncoderMethod = "getVecShiftR16OpValue";
756  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
757  let ParserMatchClass = Imm1_8Operand;
758}
759def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
760  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
761}]> {
762  let EncoderMethod = "getVecShiftR32OpValue";
763  let DecoderMethod = "DecodeVecShiftR32Imm";
764  let ParserMatchClass = Imm1_32Operand;
765}
766def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
767  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
768}]> {
769  let EncoderMethod = "getVecShiftR32OpValue";
770  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
771  let ParserMatchClass = Imm1_16Operand;
772}
773def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
774  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
775}]> {
776  let EncoderMethod = "getVecShiftR64OpValue";
777  let DecoderMethod = "DecodeVecShiftR64Imm";
778  let ParserMatchClass = Imm1_64Operand;
779}
780def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
781  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
782}]> {
783  let EncoderMethod = "getVecShiftR64OpValue";
784  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
785  let ParserMatchClass = Imm1_32Operand;
786}
787
788// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
789// (ImmLeaf)
790def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
791  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
792}]> {
793  let EncoderMethod = "getVecShiftR8OpValue";
794  let DecoderMethod = "DecodeVecShiftR8Imm";
795  let ParserMatchClass = Imm1_8Operand;
796}
797def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
798  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
799}]> {
800  let EncoderMethod = "getVecShiftR16OpValue";
801  let DecoderMethod = "DecodeVecShiftR16Imm";
802  let ParserMatchClass = Imm1_16Operand;
803}
804def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
805  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
806}]> {
807  let EncoderMethod = "getVecShiftR32OpValue";
808  let DecoderMethod = "DecodeVecShiftR32Imm";
809  let ParserMatchClass = Imm1_32Operand;
810}
811def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
812  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
813}]> {
814  let EncoderMethod = "getVecShiftR64OpValue";
815  let DecoderMethod = "DecodeVecShiftR64Imm";
816  let ParserMatchClass = Imm1_64Operand;
817}
818
819def Imm0_0Operand : AsmImmRange<0, 0>;
820def Imm0_1Operand : AsmImmRange<0, 1>;
821def Imm1_1Operand : AsmImmRange<1, 1>;
822def Imm0_3Operand : AsmImmRange<0, 3>;
823def Imm1_3Operand : AsmImmRange<1, 3>;
824def Imm0_7Operand : AsmImmRange<0, 7>;
825def Imm1_7Operand : AsmImmRange<1, 7>;
826def Imm0_15Operand : AsmImmRange<0, 15>;
827def Imm0_31Operand : AsmImmRange<0, 31>;
828def Imm0_63Operand : AsmImmRange<0, 63>;
829
830def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
831  return (((uint32_t)Imm) < 8);
832}]> {
833  let EncoderMethod = "getVecShiftL8OpValue";
834  let DecoderMethod = "DecodeVecShiftL8Imm";
835  let ParserMatchClass = Imm0_7Operand;
836}
837def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
838  return (((uint32_t)Imm) < 16);
839}]> {
840  let EncoderMethod = "getVecShiftL16OpValue";
841  let DecoderMethod = "DecodeVecShiftL16Imm";
842  let ParserMatchClass = Imm0_15Operand;
843}
844def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
845  return (((uint32_t)Imm) < 32);
846}]> {
847  let EncoderMethod = "getVecShiftL32OpValue";
848  let DecoderMethod = "DecodeVecShiftL32Imm";
849  let ParserMatchClass = Imm0_31Operand;
850}
851def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
852  return (((uint32_t)Imm) < 64);
853}]> {
854  let EncoderMethod = "getVecShiftL64OpValue";
855  let DecoderMethod = "DecodeVecShiftL64Imm";
856  let ParserMatchClass = Imm0_63Operand;
857}
858
859// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
860// (ImmLeaf)
861def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
862  return (((uint32_t)Imm) < 8);
863}]> {
864  let EncoderMethod = "getVecShiftL8OpValue";
865  let DecoderMethod = "DecodeVecShiftL8Imm";
866  let ParserMatchClass = Imm0_7Operand;
867}
868def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
869  return (((uint32_t)Imm) < 16);
870}]> {
871  let EncoderMethod = "getVecShiftL16OpValue";
872  let DecoderMethod = "DecodeVecShiftL16Imm";
873  let ParserMatchClass = Imm0_15Operand;
874}
875def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
876  return (((uint32_t)Imm) < 32);
877}]> {
878  let EncoderMethod = "getVecShiftL32OpValue";
879  let DecoderMethod = "DecodeVecShiftL32Imm";
880  let ParserMatchClass = Imm0_31Operand;
881}
882def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
883  return (((uint32_t)Imm) < 64);
884}]> {
885  let EncoderMethod = "getVecShiftL64OpValue";
886  let DecoderMethod = "DecodeVecShiftL64Imm";
887  let ParserMatchClass = Imm0_63Operand;
888}
889
890// Crazy immediate formats used by 32-bit and 64-bit logical immediate
891// instructions for splatting repeating bit patterns across the immediate.
892def logical_imm32_XFORM : SDNodeXForm<imm, [{
893  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
894  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
895}]>;
896def logical_imm64_XFORM : SDNodeXForm<imm, [{
897  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
898  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
899}]>;
900
901def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
902  GISDNodeXFormEquiv<logical_imm32_XFORM>;
903def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
904  GISDNodeXFormEquiv<logical_imm64_XFORM>;
905
906let DiagnosticType = "LogicalSecondSource" in {
907  def LogicalImm32Operand : AsmOperandClass {
908    let Name = "LogicalImm32";
909    let PredicateMethod = "isLogicalImm<int32_t>";
910    let RenderMethod = "addLogicalImmOperands<int32_t>";
911  }
912  def LogicalImm64Operand : AsmOperandClass {
913    let Name = "LogicalImm64";
914    let PredicateMethod = "isLogicalImm<int64_t>";
915    let RenderMethod = "addLogicalImmOperands<int64_t>";
916  }
917  def LogicalImm32NotOperand : AsmOperandClass {
918    let Name = "LogicalImm32Not";
919    let PredicateMethod = "isLogicalImm<int32_t>";
920    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
921  }
922  def LogicalImm64NotOperand : AsmOperandClass {
923    let Name = "LogicalImm64Not";
924    let PredicateMethod = "isLogicalImm<int64_t>";
925    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
926  }
927}
928
929def Imm0_127Operand : AsmImmRange<0, 127>;
930
931let OperandType = "OPERAND_IMMEDIATE" in {
932
933def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
934  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
935}], logical_imm32_XFORM> {
936  let PrintMethod = "printLogicalImm<int32_t>";
937  let ParserMatchClass = LogicalImm32Operand;
938}
939def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
940  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
941}], logical_imm64_XFORM> {
942  let PrintMethod = "printLogicalImm<int64_t>";
943  let ParserMatchClass = LogicalImm64Operand;
944}
945def logical_imm32_not : Operand<i32> {
946  let ParserMatchClass = LogicalImm32NotOperand;
947}
948def logical_imm64_not : Operand<i64> {
949  let ParserMatchClass = LogicalImm64NotOperand;
950}
951
952// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
953let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
954def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
955  return ((uint32_t)Imm) < 65536;
956}]>;
957
958def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
959  return ((uint64_t)Imm) < 65536;
960}]>;
961
962def imm64_0_65535 : Operand<i64>, ImmLeaf<i64, [{
963  return ((uint64_t)Imm) < 65536;
964}]>;
965} // ParserMatchClass
966
967def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
968  return ((uint32_t)Imm) < 256;
969}]> {
970  let ParserMatchClass = Imm0_255Operand;
971  let PrintMethod = "printImm";
972}
973
974// imm0_127 predicate - True if the immediate is in the range [0,127]
975def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
976  return ((uint32_t)Imm) < 128;
977}]> {
978  let ParserMatchClass = Imm0_127Operand;
979  let PrintMethod = "printImm";
980}
981
982def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
983  return ((uint64_t)Imm) < 128;
984}]> {
985  let ParserMatchClass = Imm0_127Operand;
986  let PrintMethod = "printImm";
987}
988
989// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
990// for all shift-amounts.
991
992// imm0_63 predicate - True if the immediate is in the range [0,63]
993def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
994  return ((uint64_t)Imm) < 64;
995}]> {
996  let ParserMatchClass = Imm0_63Operand;
997}
998
999def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
1000  return ((uint64_t)Imm) < 64;
1001}]> {
1002  let ParserMatchClass = Imm0_63Operand;
1003}
1004
1005// imm0_31 predicate - True if the immediate is in the range [0,31]
1006def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
1007  return ((uint64_t)Imm) < 32;
1008}]> {
1009  let ParserMatchClass = Imm0_31Operand;
1010}
1011
1012// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
1013// instead of Constant (ImmLeaf)
1014def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
1015  return ((uint64_t)Imm) < 32;
1016}]> {
1017  let ParserMatchClass = Imm0_31Operand;
1018}
1019
1020// True if the 32-bit immediate is in the range [0,31]
1021def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
1022  return ((uint64_t)Imm) < 32;
1023}]> {
1024  let ParserMatchClass = Imm0_31Operand;
1025}
1026
1027// imm0_1 predicate - True if the immediate is in the range [0,1]
1028def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
1029  return ((uint64_t)Imm) < 2;
1030}]> {
1031  let ParserMatchClass = Imm0_1Operand;
1032}
1033
1034// timm0_1 - as above, but use TargetConstant (TImmLeaf)
1035def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
1036  return ((uint64_t)Imm) < 2;
1037}]> {
1038  let ParserMatchClass = Imm0_1Operand;
1039}
1040
1041// timm32_0_0 predicate - True if the 32-bit immediate is in the range [0,0]
1042def timm32_0_0 : Operand<i32>, TImmLeaf<i32, [{
1043  return ((uint32_t)Imm) == 0;
1044}]> {
1045  let ParserMatchClass = Imm0_0Operand;
1046}
1047
1048// timm32_0_1 predicate - True if the 32-bit immediate is in the range [0,1]
1049def timm32_0_1 : Operand<i32>, TImmLeaf<i32, [{
1050  return ((uint32_t)Imm) < 2;
1051}]> {
1052  let ParserMatchClass = Imm0_1Operand;
1053}
1054
1055// timm32_1_1 - True if the 32-bit immediate is in the range [1,1]
1056def timm32_1_1 : Operand<i32>, TImmLeaf<i32, [{
1057    return ((uint32_t)Imm) == 1;
1058}]> {
1059  let ParserMatchClass = Imm1_1Operand;
1060}
1061
1062// timm32_1_3 predicate - True if the 32-bit immediate is in the range [1,3]
1063def timm32_1_3 : Operand<i32>, TImmLeaf<i32, [{
1064  return ((uint32_t)Imm) > 0 && ((uint32_t)Imm) < 4;
1065}]> {
1066  let ParserMatchClass = Imm1_3Operand;
1067}
1068
1069// imm0_15 predicate - True if the immediate is in the range [0,15]
1070def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
1071  return ((uint64_t)Imm) < 16;
1072}]> {
1073  let ParserMatchClass = Imm0_15Operand;
1074}
1075
1076// imm0_7 predicate - True if the immediate is in the range [0,7]
1077def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
1078  return ((uint64_t)Imm) < 8;
1079}]> {
1080  let ParserMatchClass = Imm0_7Operand;
1081}
1082
1083// imm0_3 predicate - True if the immediate is in the range [0,3]
1084def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
1085  return ((uint64_t)Imm) < 4;
1086}]> {
1087  let ParserMatchClass = Imm0_3Operand;
1088}
1089
1090// timm32_0_3 predicate - True if the 32-bit immediate is in the range [0,3]
1091def timm32_0_3 : Operand<i32>, TImmLeaf<i32, [{
1092  return ((uint32_t)Imm) < 4;
1093}]> {
1094  let ParserMatchClass = Imm0_3Operand;
1095}
1096
1097// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
1098def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
1099  return ((uint32_t)Imm) < 8;
1100}]> {
1101  let ParserMatchClass = Imm0_7Operand;
1102}
1103
1104// timm32_1_7 predicate - True if the 32-bit immediate is in the range [1,7]
1105def timm32_1_7 : Operand<i32>, TImmLeaf<i32, [{
1106  return ((uint32_t)Imm) > 0 && ((uint32_t)Imm) < 8;
1107}]> {
1108  let ParserMatchClass = Imm1_7Operand;
1109}
1110
1111// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1112def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
1113  return ((uint32_t)Imm) < 16;
1114}]> {
1115  let ParserMatchClass = Imm0_15Operand;
1116}
1117
1118// timm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1119def timm32_0_15 : Operand<i32>, TImmLeaf<i32, [{
1120  return ((uint32_t)Imm) < 16;
1121}]> {
1122  let ParserMatchClass = Imm0_15Operand;
1123}
1124
1125// timm32_0_31 predicate - True if the 32-bit immediate is in the range [0,31]
1126def timm32_0_31 : Operand<i32>, TImmLeaf<i32, [{
1127  return ((uint32_t)Imm) < 32;
1128}]> {
1129  let ParserMatchClass = Imm0_31Operand;
1130}
1131
1132// timm32_0_255 predicate - True if the 32-bit immediate is in the range [0,255]
1133def timm32_0_255 : Operand<i32>, TImmLeaf<i32, [{
1134  return ((uint32_t)Imm) < 256;
1135}]> {
1136  let ParserMatchClass = Imm0_255Operand;
1137}
1138
1139} // let OperandType = "OPERAND_IMMEDIATE"
1140
1141// An arithmetic shifter operand:
1142//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
1143//  {5-0} - imm6
1144class arith_shift<ValueType Ty, int width> : Operand<Ty> {
1145  let PrintMethod = "printShifter";
1146  let ParserMatchClass = !cast<AsmOperandClass>(
1147                         "ArithmeticShifterOperand" # width);
1148}
1149
1150def arith_shift32 : arith_shift<i32, 32>;
1151def arith_shift64 : arith_shift<i64, 64>;
1152
1153class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
1154    : Operand<Ty>,
1155      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
1156  let PrintMethod = "printShiftedRegister";
1157  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
1158}
1159
1160def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
1161def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
1162
1163def gi_arith_shifted_reg32 :
1164  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1165  GIComplexPatternEquiv<arith_shifted_reg32>;
1166
1167def gi_arith_shifted_reg64 :
1168  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1169  GIComplexPatternEquiv<arith_shifted_reg64>;
1170
1171// An arithmetic shifter operand:
1172//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1173//  {5-0} - imm6
1174class logical_shift<int width> : Operand<i32> {
1175  let PrintMethod = "printShifter";
1176  let ParserMatchClass = !cast<AsmOperandClass>(
1177                         "LogicalShifterOperand" # width);
1178}
1179
1180def logical_shift32 : logical_shift<32>;
1181def logical_shift64 : logical_shift<64>;
1182
1183class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1184    : Operand<Ty>,
1185      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1186  let PrintMethod = "printShiftedRegister";
1187  let MIOperandInfo = (ops regclass, shiftop);
1188}
1189
1190def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1191def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1192
1193def gi_logical_shifted_reg32 :
1194  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1195  GIComplexPatternEquiv<logical_shifted_reg32>;
1196
1197def gi_logical_shifted_reg64 :
1198  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1199  GIComplexPatternEquiv<logical_shifted_reg64>;
1200
1201// A logical vector shifter operand:
1202//  {7-6} - shift type: 00 = lsl
1203//  {5-0} - imm6: #0, #8, #16, or #24
1204def logical_vec_shift : Operand<i32> {
1205  let PrintMethod = "printShifter";
1206  let EncoderMethod = "getVecShifterOpValue";
1207  let ParserMatchClass = LogicalVecShifterOperand;
1208}
1209
1210// A logical vector half-word shifter operand:
1211//  {7-6} - shift type: 00 = lsl
1212//  {5-0} - imm6: #0 or #8
1213def logical_vec_hw_shift : Operand<i32> {
1214  let PrintMethod = "printShifter";
1215  let EncoderMethod = "getVecShifterOpValue";
1216  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1217}
1218
1219// A vector move shifter operand:
1220//  {0} - imm1: #8 or #16
1221def move_vec_shift : Operand<i32> {
1222  let PrintMethod = "printShifter";
1223  let EncoderMethod = "getMoveVecShifterOpValue";
1224  let ParserMatchClass = MoveVecShifterOperand;
1225}
1226
1227let DiagnosticType = "AddSubSecondSource" in {
1228  def AddSubImmOperand : AsmOperandClass {
1229    let Name = "AddSubImm";
1230    let ParserMethod = "tryParseImmWithOptionalShift";
1231    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1232  }
1233  def AddSubImmNegOperand : AsmOperandClass {
1234    let Name = "AddSubImmNeg";
1235    let ParserMethod = "tryParseImmWithOptionalShift";
1236    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1237  }
1238}
1239// An ADD/SUB immediate shifter operand:
1240//  second operand:
1241//  {7-6} - shift type: 00 = lsl
1242//  {5-0} - imm6: #0 or #12
1243class addsub_shifted_imm<ValueType Ty>
1244    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1245  let PrintMethod = "printAddSubImm";
1246  let EncoderMethod = "getAddSubImmOpValue";
1247  let ParserMatchClass = AddSubImmOperand;
1248  let MIOperandInfo = (ops i32imm, i32imm);
1249}
1250
1251class addsub_shifted_imm_neg<ValueType Ty>
1252    : Operand<Ty> {
1253  let EncoderMethod = "getAddSubImmOpValue";
1254  let ParserMatchClass = AddSubImmNegOperand;
1255  let MIOperandInfo = (ops i32imm, i32imm);
1256}
1257
1258def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1259def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1260def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1261def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1262
1263def gi_addsub_shifted_imm32 :
1264    GIComplexOperandMatcher<s32, "selectArithImmed">,
1265    GIComplexPatternEquiv<addsub_shifted_imm32>;
1266
1267def gi_addsub_shifted_imm64 :
1268    GIComplexOperandMatcher<s64, "selectArithImmed">,
1269    GIComplexPatternEquiv<addsub_shifted_imm64>;
1270
1271class neg_addsub_shifted_imm<ValueType Ty>
1272    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1273  let PrintMethod = "printAddSubImm";
1274  let EncoderMethod = "getAddSubImmOpValue";
1275  let ParserMatchClass = AddSubImmOperand;
1276  let MIOperandInfo = (ops i32imm, i32imm);
1277}
1278
1279def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1280def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1281
1282def gi_neg_addsub_shifted_imm32 :
1283    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1284    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1285
1286def gi_neg_addsub_shifted_imm64 :
1287    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1288    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1289
1290// An extend operand:
1291//  {5-3} - extend type
1292//  {2-0} - imm3
1293def arith_extend : Operand<i32> {
1294  let PrintMethod = "printArithExtend";
1295  let ParserMatchClass = ExtendOperand;
1296}
1297def arith_extend64 : Operand<i32> {
1298  let PrintMethod = "printArithExtend";
1299  let ParserMatchClass = ExtendOperand64;
1300}
1301
1302// 'extend' that's a lsl of a 64-bit register.
1303def arith_extendlsl64 : Operand<i32> {
1304  let PrintMethod = "printArithExtend";
1305  let ParserMatchClass = ExtendOperandLSL64;
1306}
1307
1308class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1309                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1310  let PrintMethod = "printExtendedRegister";
1311  let MIOperandInfo = (ops GPR32, arith_extend);
1312}
1313
1314class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1315                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1316  let PrintMethod = "printExtendedRegister";
1317  let MIOperandInfo = (ops GPR32, arith_extend64);
1318}
1319
1320def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1321def gi_arith_extended_reg32_i32 :
1322    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1323    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1324
1325def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1326def gi_arith_extended_reg32_i64 :
1327    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1328    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1329
1330def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1331def gi_arith_extended_reg32to64_i64 :
1332    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1333    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1334
1335def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
1336
1337// Floating-point immediate.
1338
1339def fpimm16XForm : SDNodeXForm<fpimm, [{
1340      APFloat InVal = N->getValueAPF();
1341      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1342      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1343    }]>;
1344
1345def fpimm32XForm : SDNodeXForm<fpimm, [{
1346      APFloat InVal = N->getValueAPF();
1347      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1348      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1349    }]>;
1350
1351def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1352      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1353                                                          .bitcastToAPInt()
1354                                                          .getZExtValue());
1355      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1356    }]>;
1357
1358def fpimm64XForm : SDNodeXForm<fpimm, [{
1359      APFloat InVal = N->getValueAPF();
1360      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1361      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1362    }]>;
1363
1364def fpimm16 : Operand<f16>,
1365              FPImmLeaf<f16, [{
1366      return AArch64_AM::getFP16Imm(Imm) != -1;
1367    }], fpimm16XForm> {
1368  let ParserMatchClass = FPImmOperand;
1369  let PrintMethod = "printFPImmOperand";
1370}
1371
1372def fpimmbf16 : Operand<bf16>,
1373                FPImmLeaf<bf16, [{
1374      return AArch64_AM::getFP16Imm(Imm) != -1;
1375    }], fpimm16XForm>;
1376
1377def fpimm32 : Operand<f32>,
1378              FPImmLeaf<f32, [{
1379      return AArch64_AM::getFP32Imm(Imm) != -1;
1380    }], fpimm32XForm> {
1381  let ParserMatchClass = FPImmOperand;
1382  let PrintMethod = "printFPImmOperand";
1383}
1384
1385def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1386      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1387      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1388    }], fpimm32SIMDModImmType4XForm> {
1389}
1390
1391def fpimm64 : Operand<f64>,
1392              FPImmLeaf<f64, [{
1393      return AArch64_AM::getFP64Imm(Imm) != -1;
1394    }], fpimm64XForm> {
1395  let ParserMatchClass = FPImmOperand;
1396  let PrintMethod = "printFPImmOperand";
1397}
1398
1399def fpimm8 : Operand<i32> {
1400  let ParserMatchClass = FPImmOperand;
1401  let PrintMethod = "printFPImmOperand";
1402}
1403
1404def fpimm0 : FPImmLeaf<fAny, [{
1405  return Imm.isExactlyValue(+0.0);
1406}]>;
1407
1408def fpimm_minus0 : FPImmLeaf<fAny, [{
1409  return Imm.isExactlyValue(-0.0);
1410}]>;
1411
1412def fpimm_half : FPImmLeaf<fAny, [{
1413  return Imm.isExactlyValue(+0.5);
1414}]>;
1415
1416def fpimm_one : FPImmLeaf<fAny, [{
1417  return Imm.isExactlyValue(+1.0);
1418}]>;
1419
1420def fpimm_two : FPImmLeaf<fAny, [{
1421  return Imm.isExactlyValue(+2.0);
1422}]>;
1423
1424def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1425  GISDNodeXFormEquiv<fpimm16XForm>;
1426def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1427  GISDNodeXFormEquiv<fpimm32XForm>;
1428def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1429  GISDNodeXFormEquiv<fpimm64XForm>;
1430def gi_fpimm32SIMDModImmType4 :
1431    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1432  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1433
1434// Vector lane operands
1435class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1436  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1437  let DiagnosticType = "Invalid" # Name;
1438  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1439  let RenderMethod = "addVectorIndexOperands";
1440}
1441
1442class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1443    : Operand<ty> {
1444  let ParserMatchClass = mc;
1445  let PrintMethod = "printVectorIndex";
1446}
1447
1448multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1449  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1450  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1451}
1452
1453def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1454def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1455def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1456def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1457def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1458def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1459
1460let OperandNamespace = "AArch64" in {
1461  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1462    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1463                                [{ return ((uint64_t)Imm) == 0; }]>;
1464    defm VectorIndex032b : VectorIndex<i32, VectorIndex0Operand,
1465                                [{ return ((uint32_t)Imm) == 0; }]>;
1466  }
1467}
1468defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1469                                [{ return ((uint64_t)Imm) == 1; }]>;
1470defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1471                                [{ return ((uint64_t)Imm) < 16; }]>;
1472defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1473                                [{ return ((uint64_t)Imm) < 8; }]>;
1474defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1475                                [{ return ((uint64_t)Imm) < 4; }]>;
1476defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1477                                [{ return ((uint64_t)Imm) < 2; }]>;
1478
1479defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1480                                   [{ return ((uint64_t)Imm) == 1; }]>;
1481defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1482                                   [{ return ((uint64_t)Imm) < 16; }]>;
1483defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1484                                   [{ return ((uint64_t)Imm) < 8; }]>;
1485defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1486                                   [{ return ((uint64_t)Imm) < 4; }]>;
1487defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1488                                   [{ return ((uint64_t)Imm) < 2; }]>;
1489
1490def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1491def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1492def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1493def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1494def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1495
1496defm sve_elm_idx_extdup_b
1497  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1498                [{ return ((uint64_t)Imm) < 64; }]>;
1499defm sve_elm_idx_extdup_h
1500  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1501                [{ return ((uint64_t)Imm) < 32; }]>;
1502defm sve_elm_idx_extdup_s
1503  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1504                [{ return ((uint64_t)Imm) < 16; }]>;
1505defm sve_elm_idx_extdup_d
1506  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1507                [{ return ((uint64_t)Imm) < 8; }]>;
1508defm sve_elm_idx_extdup_q
1509  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1510                [{ return ((uint64_t)Imm) < 4; }]>;
1511
1512def sme_elm_idx0_0 : Operand<i32>, TImmLeaf<i32, [{
1513  return ((uint32_t)Imm) == 0;
1514}]> {
1515  let ParserMatchClass = Imm0_0Operand;
1516  let PrintMethod = "printMatrixIndex";
1517  let OperandNamespace = "AArch64";
1518  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1519}
1520def sme_elm_idx0_1 : Operand<i32>, TImmLeaf<i32, [{
1521  return ((uint32_t)Imm) <= 1;
1522}]> {
1523  let ParserMatchClass = Imm0_1Operand;
1524  let PrintMethod = "printMatrixIndex";
1525}
1526def sme_elm_idx0_3 : Operand<i32>, TImmLeaf<i32, [{
1527  return ((uint32_t)Imm) <= 3;
1528}]> {
1529  let ParserMatchClass = Imm0_3Operand;
1530  let PrintMethod = "printMatrixIndex";
1531}
1532def sme_elm_idx0_7 : Operand<i32>, TImmLeaf<i32, [{
1533  return ((uint32_t)Imm) <= 7;
1534}]> {
1535  let ParserMatchClass = Imm0_7Operand;
1536  let PrintMethod = "printMatrixIndex";
1537}
1538def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
1539  return ((uint32_t)Imm) <= 15;
1540}]> {
1541  let ParserMatchClass = Imm0_15Operand;
1542  let PrintMethod = "printMatrixIndex";
1543}
1544
1545// SME2 vector select offset operands
1546
1547// uimm3s8 predicate
1548// True if the immediate is a multiple of 8 in the range [0,56].
1549def UImm3s8Operand : UImmScaledMemoryIndexed<3, 8>;
1550
1551def uimm3s8 : Operand<i64>, ImmLeaf<i64,
1552[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
1553  let PrintMethod = "printMatrixIndex<8>";
1554  let ParserMatchClass = UImm3s8Operand;
1555}
1556
1557class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
1558  let Name = "UImm" # Width # "s" # Scale # "Range";
1559  let DiagnosticType = "InvalidMemoryIndexedRange" # Scale # "UImm" # Width;
1560  let RenderMethod = "addImmScaledRangeOperands<" # Scale # ">";
1561  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ", " # OffsetVal # ", /*IsRange=*/true>";
1562  let ParserMethod = "tryParseImmRange";
1563}
1564
1565// Implicit immediate ranges 0:1 and 0:3, scale has no meaning
1566// since the immediate is zero
1567def UImm0s2RangeOperand : UImmScaledMemoryIndexedRange<0, 2, 1>;
1568def UImm0s4RangeOperand : UImmScaledMemoryIndexedRange<0, 4, 3>;
1569
1570def UImm1s2RangeOperand : UImmScaledMemoryIndexedRange<1, 2, 1>;
1571def UImm1s4RangeOperand : UImmScaledMemoryIndexedRange<1, 4, 3>;
1572def UImm2s2RangeOperand : UImmScaledMemoryIndexedRange<2, 2, 1>;
1573def UImm2s4RangeOperand : UImmScaledMemoryIndexedRange<2, 4, 3>;
1574def UImm3s2RangeOperand : UImmScaledMemoryIndexedRange<3, 2, 1>;
1575
1576def uimm0s2range : Operand<i64>, ImmLeaf<i64,
1577[{ return Imm == 0; }], UImmS1XForm> {
1578  let PrintMethod = "printImmRangeScale<2, 1>";
1579  let ParserMatchClass = UImm0s2RangeOperand;
1580  let OperandNamespace = "AArch64";
1581  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1582}
1583
1584def uimm0s4range : Operand<i64>, ImmLeaf<i64,
1585[{ return Imm == 0; }], UImmS1XForm> {
1586  let PrintMethod = "printImmRangeScale<4, 3>";
1587  let ParserMatchClass = UImm0s4RangeOperand;
1588  let OperandNamespace = "AArch64";
1589  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1590}
1591
1592def uimm1s2range : Operand<i64>, ImmLeaf<i64,
1593[{ return Imm >= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> {
1594  let PrintMethod = "printImmRangeScale<2, 1>";
1595  let ParserMatchClass = UImm1s2RangeOperand;
1596}
1597
1598def uimm1s4range : Operand<i64>, ImmLeaf<i64,
1599[{ return Imm >= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> {
1600  let PrintMethod = "printImmRangeScale<4, 3>";
1601  let ParserMatchClass = UImm1s4RangeOperand;
1602}
1603
1604def uimm2s2range : Operand<i64>, ImmLeaf<i64,
1605[{ return Imm >= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> {
1606  let PrintMethod = "printImmRangeScale<2, 1>";
1607  let ParserMatchClass = UImm2s2RangeOperand;
1608}
1609
1610def uimm2s4range : Operand<i64>, ImmLeaf<i64,
1611[{ return Imm >= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> {
1612  let PrintMethod = "printImmRangeScale<4, 3>";
1613  let ParserMatchClass = UImm2s4RangeOperand;
1614}
1615
1616def uimm3s2range : Operand<i64>, ImmLeaf<i64,
1617[{ return Imm >= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> {
1618  let PrintMethod = "printImmRangeScale<2, 1>";
1619  let ParserMatchClass = UImm3s2RangeOperand;
1620}
1621
1622
1623// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1624// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1625// are encoded as the eight bit value 'abcdefgh'.
1626def simdimmtype10 : Operand<i32>,
1627                    FPImmLeaf<f64, [{
1628      return AArch64_AM::isAdvSIMDModImmType10(
1629                 Imm.bitcastToAPInt().getZExtValue());
1630    }], SDNodeXForm<fpimm, [{
1631      APFloat InVal = N->getValueAPF();
1632      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1633                                                           .bitcastToAPInt()
1634                                                           .getZExtValue());
1635      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1636    }]>> {
1637  let ParserMatchClass = SIMDImmType10Operand;
1638  let PrintMethod = "printSIMDType10Operand";
1639}
1640
1641
1642//---
1643// System management
1644//---
1645
1646// Base encoding for system instruction operands.
1647let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1648class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1649                  list<dag> pattern = []>
1650    : I<oops, iops, asm, operands, "", pattern> {
1651  let Inst{31-22} = 0b1101010100;
1652  let Inst{21}    = L;
1653}
1654
1655// System instructions which do not have an Rt register.
1656class SimpleSystemI<bit L, dag iops, string asm, string operands,
1657                    list<dag> pattern = []>
1658    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1659  let Inst{4-0} = 0b11111;
1660}
1661
1662// System instructions which have an Rt register.
1663class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1664                list<dag> pattern = []>
1665    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1666      Sched<[WriteSys]> {
1667  bits<5> Rt;
1668  let Inst{4-0} = Rt;
1669}
1670
1671// System instructions for transactional memory extension
1672class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1673                    string asm, string operands, list<dag> pattern>
1674    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1675      Sched<[WriteSys]> {
1676  let Inst{20-12} = 0b000110011;
1677  let Inst{11-8} = CRm;
1678  let Inst{7-5} = op2;
1679  let DecoderMethod = "";
1680
1681  let mayLoad = 1;
1682  let mayStore = 1;
1683}
1684
1685// System instructions for transactional memory - single input operand
1686class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1687    : TMBaseSystemI<0b1, CRm, 0b011,
1688                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1689  bits<5> Rt;
1690  let Inst{4-0} = Rt;
1691}
1692
1693// System instructions that pass a register argument
1694// This class assumes the register is for input rather than output.
1695class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1696                      list<dag> pattern = []>
1697    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1698  let Inst{20-12} = 0b000110001;
1699  let Inst{11-8} = CRm;
1700  let Inst{7-5} = Op2;
1701}
1702
1703// System instructions for transactional memory - no operand
1704class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1705    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1706  let Inst{4-0} = 0b11111;
1707}
1708
1709// System instructions for exit from transactions
1710class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1711    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1712      Sched<[WriteSys]> {
1713  bits<16> imm;
1714  let Inst{31-24} = 0b11010100;
1715  let Inst{23-21} = op1;
1716  let Inst{20-5}  = imm;
1717  let Inst{4-0}   = 0b00000;
1718}
1719
1720// Hint instructions that take both a CRm and a 3-bit immediate.
1721// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1722// model patterns with sufficiently fine granularity
1723let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1724  class HintI<string mnemonic>
1725      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1726                      [(int_aarch64_hint imm0_127:$imm)]>,
1727        Sched<[WriteHint]> {
1728    bits <7> imm;
1729    let Inst{20-12} = 0b000110010;
1730    let Inst{11-5} = imm;
1731  }
1732
1733// System instructions taking a single literal operand which encodes into
1734// CRm. op2 differentiates the opcodes.
1735def BarrierAsmOperand : AsmOperandClass {
1736  let Name = "Barrier";
1737  let ParserMethod = "tryParseBarrierOperand";
1738}
1739def barrier_op : Operand<i32> {
1740  let PrintMethod = "printBarrierOption";
1741  let ParserMatchClass = BarrierAsmOperand;
1742}
1743def BarriernXSAsmOperand : AsmOperandClass {
1744  let Name = "BarriernXS";
1745  let ParserMethod = "tryParseBarriernXSOperand";
1746}
1747def barrier_nxs_op : Operand<i32> {
1748  let PrintMethod = "printBarriernXSOption";
1749  let ParserMatchClass = BarriernXSAsmOperand;
1750}
1751class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1752                 list<dag> pattern = []>
1753    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1754      Sched<[WriteBarrier]> {
1755  bits<4> CRm;
1756  let Inst{20-12} = 0b000110011;
1757  let Inst{11-8} = CRm;
1758  let Inst{7-5} = opc;
1759}
1760
1761class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1762    : SimpleSystemI<0, (ins), asm, "", pattern>,
1763      Sched<[WriteHint]> {
1764  bits<4> CRm;
1765  let CRm = 0b0011;
1766  let Inst{31-12} = 0b11010101000000110010;
1767  let Inst{11-8} = CRm;
1768  let Inst{7-5} = op2;
1769  let Inst{4-0} = 0b11111;
1770}
1771
1772// MRS/MSR system instructions. These have different operand classes because
1773// a different subset of registers can be accessed through each instruction.
1774def MRSSystemRegisterOperand : AsmOperandClass {
1775  let Name = "MRSSystemRegister";
1776  let ParserMethod = "tryParseSysReg";
1777  let DiagnosticType = "MRS";
1778}
1779// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1780def mrs_sysreg_op : Operand<i32> {
1781  let ParserMatchClass = MRSSystemRegisterOperand;
1782  let DecoderMethod = "DecodeMRSSystemRegister";
1783  let PrintMethod = "printMRSSystemRegister";
1784}
1785
1786def MSRSystemRegisterOperand : AsmOperandClass {
1787  let Name = "MSRSystemRegister";
1788  let ParserMethod = "tryParseSysReg";
1789  let DiagnosticType = "MSR";
1790}
1791def msr_sysreg_op : Operand<i32> {
1792  let ParserMatchClass = MSRSystemRegisterOperand;
1793  let DecoderMethod = "DecodeMSRSystemRegister";
1794  let PrintMethod = "printMSRSystemRegister";
1795}
1796
1797def PSBHintOperand : AsmOperandClass {
1798  let Name = "PSBHint";
1799  let ParserMethod = "tryParsePSBHint";
1800}
1801def psbhint_op : Operand<i32> {
1802  let ParserMatchClass = PSBHintOperand;
1803  let PrintMethod = "printPSBHintOp";
1804  let MCOperandPredicate = [{
1805    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1806    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1807    if (!MCOp.isImm())
1808      return false;
1809    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1810  }];
1811}
1812
1813def BTIHintOperand : AsmOperandClass {
1814  let Name = "BTIHint";
1815  let ParserMethod = "tryParseBTIHint";
1816}
1817def btihint_op : Operand<i32> {
1818  let ParserMatchClass = BTIHintOperand;
1819  let PrintMethod = "printBTIHintOp";
1820  let MCOperandPredicate = [{
1821    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1822    if (!MCOp.isImm())
1823      return false;
1824    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1825  }];
1826}
1827
1828class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1829                       "mrs", "\t$Rt, $systemreg"> {
1830  bits<16> systemreg;
1831  let Inst{20-5} = systemreg;
1832  let DecoderNamespace = "Fallback";
1833  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1834  // require doing this. The alternative was to explicitly model each one, but
1835  // it feels like it is unnecessary because it seems there are no negative
1836  // consequences setting these flags for all.
1837  let Defs = [NZCV];
1838}
1839
1840// FIXME: Some of these def NZCV, others don't. Best way to model that?
1841// Explicitly modeling each of the system register as a register class
1842// would do it, but feels like overkill at this point.
1843class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1844                       "msr", "\t$systemreg, $Rt"> {
1845  bits<16> systemreg;
1846  let Inst{20-5} = systemreg;
1847  let DecoderNamespace = "Fallback";
1848}
1849
1850def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1851  let Name = "SystemPStateFieldWithImm0_15";
1852  let ParserMethod = "tryParseSysReg";
1853}
1854def pstatefield4_op : Operand<i32> {
1855  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1856  let PrintMethod = "printSystemPStateField";
1857  let MCOperandPredicate = [{
1858    if (!MCOp.isImm())
1859      return false;
1860    return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr;
1861  }];
1862}
1863
1864// Instructions to modify PSTATE, no input reg
1865let Defs = [NZCV] in
1866class PstateWriteSimple<dag iops, string asm, string operands>
1867  : SimpleSystemI<0, iops, asm, operands> {
1868
1869  let Inst{20-19} = 0b00;
1870  let Inst{15-12} = 0b0100;
1871}
1872
1873class MSRpstateImm0_15
1874  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1875                  "\t$pstatefield, $imm">,
1876    Sched<[WriteSys]> {
1877
1878  bits<6> pstatefield;
1879  bits<4> imm;
1880  let Inst{18-16} = pstatefield{5-3};
1881  let Inst{11-8} = imm;
1882  let Inst{7-5} = pstatefield{2-0};
1883
1884  let DecoderMethod = "DecodeSystemPStateImm0_15Instruction";
1885  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1886  // Fail the decoder should attempt to decode the instruction as MSRI.
1887  let hasCompleteDecoder = false;
1888}
1889
1890def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1891  let Name = "SystemPStateFieldWithImm0_1";
1892  let ParserMethod = "tryParseSysReg";
1893}
1894def pstatefield1_op : Operand<i32> {
1895  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1896  let PrintMethod = "printSystemPStateField";
1897  let MCOperandPredicate = [{
1898    if (!MCOp.isImm())
1899      return false;
1900    return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr;
1901  }];
1902}
1903
1904class MSRpstateImm0_1
1905  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1906                 "\t$pstatefield, $imm">,
1907    Sched<[WriteSys]> {
1908
1909  bits<9> pstatefield;
1910  bit imm;
1911  let Inst{18-16} = pstatefield{5-3};
1912  let Inst{11-9} = pstatefield{8-6};
1913  let Inst{8} = imm;
1914  let Inst{7-5} = pstatefield{2-0};
1915
1916  let DecoderMethod = "DecodeSystemPStateImm0_1Instruction";
1917  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1918  // Fail the decoder should attempt to decode the instruction as MSRI.
1919  let hasCompleteDecoder = false;
1920  let DecoderNamespace = "Fallback";
1921}
1922
1923// SYS and SYSL generic system instructions.
1924def SysCRAsmOperand : AsmOperandClass {
1925  let Name = "SysCR";
1926  let ParserMethod = "tryParseSysCROperand";
1927}
1928
1929def sys_cr_op : Operand<i32> {
1930  let PrintMethod = "printSysCROperand";
1931  let ParserMatchClass = SysCRAsmOperand;
1932}
1933
1934class SystemXtI<bit L, string asm>
1935  : RtSystemI<L, (outs),
1936       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1937       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1938  bits<3> op1;
1939  bits<4> Cn;
1940  bits<4> Cm;
1941  bits<3> op2;
1942  let Inst{20-19} = 0b01;
1943  let Inst{18-16} = op1;
1944  let Inst{15-12} = Cn;
1945  let Inst{11-8}  = Cm;
1946  let Inst{7-5}   = op2;
1947}
1948
1949class SystemLXtI<bit L, string asm>
1950  : RtSystemI<L, (outs),
1951       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1952       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1953  bits<3> op1;
1954  bits<4> Cn;
1955  bits<4> Cm;
1956  bits<3> op2;
1957  let Inst{20-19} = 0b01;
1958  let Inst{18-16} = op1;
1959  let Inst{15-12} = Cn;
1960  let Inst{11-8}  = Cm;
1961  let Inst{7-5}   = op2;
1962}
1963
1964def RangePrefetchOperand : AsmOperandClass {
1965  let Name = "RangePrefetch";
1966  let ParserMethod = "tryParseRPRFMOperand";
1967  let PredicateMethod = "isPrefetch";
1968  let RenderMethod = "addPrefetchOperands";
1969}
1970
1971def rprfop : Operand<i32>, TImmLeaf<i32, [{
1972    return (((uint32_t)Imm) <= 63);
1973  }]> {
1974  let PrintMethod = "printRPRFMOperand";
1975  let ParserMatchClass = RangePrefetchOperand;
1976}
1977
1978// Branch (register) instructions:
1979//
1980//  case opc of
1981//    0001 blr
1982//    0000 br
1983//    0101 dret
1984//    0100 eret
1985//    0010 ret
1986//    otherwise UNDEFINED
1987class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1988                    string operands, list<dag> pattern>
1989    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1990  let Inst{31-25} = 0b1101011;
1991  let Inst{24-21} = opc;
1992  let Inst{20-16} = 0b11111;
1993  let Inst{15-10} = 0b000000;
1994  let Inst{4-0}   = 0b00000;
1995}
1996
1997class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1998    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1999  bits<5> Rn;
2000  let Inst{9-5} = Rn;
2001}
2002
2003let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
2004class SpecialReturn<bits<4> opc, string asm>
2005    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
2006  let Inst{9-5} = 0b11111;
2007}
2008
2009let mayLoad = 1 in
2010class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
2011  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
2012  Sched<[]> {
2013  bits<5> Rn;
2014  bits<5> Rt;
2015  let Inst{31-30} = sz;
2016  let Inst{29-10} = 0b11100010111111110000;
2017  let Inst{9-5} = Rn;
2018  let Inst{4-0} = Rt;
2019}
2020
2021class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
2022               list<dag> pattern>
2023  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
2024  let isAuthenticated = 1;
2025  let Inst{31-25} = 0b1101011;
2026  let Inst{20-11} = 0b1111100001;
2027  let Inst{10} = M;
2028  let Inst{4-0} = 0b11111;
2029}
2030
2031class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
2032  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
2033  bits<5> Rn;
2034  bits<5> Rm;
2035  let Inst{24-22} = 0b100;
2036  let Inst{21} = op;
2037  let Inst{9-5} = Rn;
2038  let Inst{4-0} = Rm;
2039}
2040
2041class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
2042  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
2043  bits<5> Rn;
2044  let Inst{24} = 0;
2045  let Inst{23-21} = opc;
2046  let Inst{9-5} = Rn;
2047}
2048
2049let Uses = [LR,SP] in
2050class AuthReturn<bits<3> op, bits<1> M, string asm>
2051  : AuthBase<M, (outs), (ins), asm, "", []> {
2052  let Inst{24} = 0;
2053  let Inst{23-21} = op;
2054  let Inst{9-0} = 0b1111111111;
2055}
2056
2057let mayLoad = 1 in
2058class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
2059                   string operands, string cstr>
2060  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
2061  bits<10> offset;
2062  bits<5> Rn;
2063  bits<5> Rt;
2064  let isAuthenticated = 1;
2065  let Inst{31-24} = 0b11111000;
2066  let Inst{23} = M;
2067  let Inst{22} = offset{9};
2068  let Inst{21} = 1;
2069  let Inst{20-12} = offset{8-0};
2070  let Inst{11} = W;
2071  let Inst{10} = 1;
2072  let Inst{9-5} = Rn;
2073  let Inst{4-0} = Rt;
2074
2075  let DecoderMethod = "DecodeAuthLoadInstruction";
2076}
2077
2078multiclass AuthLoad<bit M, string asm, Operand opr> {
2079  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
2080                               (ins GPR64sp:$Rn, opr:$offset),
2081                               asm, "\t$Rt, [$Rn, $offset]", "">;
2082  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
2083                               (ins GPR64sp:$Rn, opr:$offset),
2084                               asm, "\t$Rt, [$Rn, $offset]!",
2085                               "$Rn = $wback,@earlyclobber $wback">;
2086
2087  def : InstAlias<asm # "\t$Rt, [$Rn]",
2088                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
2089
2090  def : InstAlias<asm # "\t$Rt, [$wback]!",
2091                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
2092}
2093
2094//---
2095// Conditional branch instruction.
2096//---
2097
2098// Condition code.
2099// 4-bit immediate. Pretty-printed as <cc>
2100def ccode : Operand<i32> {
2101  let PrintMethod = "printCondCode";
2102  let ParserMatchClass = CondCode;
2103}
2104def inv_ccode : Operand<i32> {
2105  // AL and NV are invalid in the aliases which use inv_ccode
2106  let PrintMethod = "printInverseCondCode";
2107  let ParserMatchClass = CondCode;
2108  let MCOperandPredicate = [{
2109    return MCOp.isImm() &&
2110           MCOp.getImm() != AArch64CC::AL &&
2111           MCOp.getImm() != AArch64CC::NV;
2112  }];
2113}
2114
2115// Conditional branch target. 19-bit immediate. The low two bits of the target
2116// offset are implied zero and so are not part of the immediate.
2117def am_brcond : Operand<OtherVT> {
2118  let EncoderMethod = "getCondBranchTargetOpValue";
2119  let DecoderMethod = "DecodePCRelLabel19";
2120  let PrintMethod = "printAlignedLabel";
2121  let ParserMatchClass = PCRelLabel19Operand;
2122  let OperandType = "OPERAND_PCREL";
2123}
2124
2125class BranchCond<bit bit4, string mnemonic>
2126   : I<(outs), (ins ccode:$cond, am_brcond:$target),
2127       mnemonic, ".$cond\t$target", "",
2128       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
2129  let isBranch = 1;
2130  let isTerminator = 1;
2131  let Uses = [NZCV];
2132
2133  bits<4> cond;
2134  bits<19> target;
2135  let Inst{31-24} = 0b01010100;
2136  let Inst{23-5} = target;
2137  let Inst{4} = bit4;
2138  let Inst{3-0} = cond;
2139}
2140
2141//---
2142// Compare-and-branch instructions.
2143//---
2144class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
2145    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
2146         asm, "\t$Rt, $target", "",
2147         [(node regtype:$Rt, bb:$target)]>,
2148      Sched<[WriteBr]> {
2149  let isBranch = 1;
2150  let isTerminator = 1;
2151
2152  bits<5> Rt;
2153  bits<19> target;
2154  let Inst{30-25} = 0b011010;
2155  let Inst{24}    = op;
2156  let Inst{23-5}  = target;
2157  let Inst{4-0}   = Rt;
2158}
2159
2160multiclass CmpBranch<bit op, string asm, SDNode node> {
2161  def W : BaseCmpBranch<GPR32, op, asm, node> {
2162    let Inst{31} = 0;
2163  }
2164  def X : BaseCmpBranch<GPR64, op, asm, node> {
2165    let Inst{31} = 1;
2166  }
2167}
2168
2169//---
2170// Test-bit-and-branch instructions.
2171//---
2172// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
2173// the target offset are implied zero and so are not part of the immediate.
2174def am_tbrcond : Operand<OtherVT> {
2175  let EncoderMethod = "getTestBranchTargetOpValue";
2176  let PrintMethod = "printAlignedLabel";
2177  let ParserMatchClass = BranchTarget14Operand;
2178  let OperandType = "OPERAND_PCREL";
2179}
2180
2181// AsmOperand classes to emit (or not) special diagnostics
2182def TBZImm0_31Operand : AsmOperandClass {
2183  let Name = "TBZImm0_31";
2184  let PredicateMethod = "isImmInRange<0,31>";
2185  let RenderMethod = "addImmOperands";
2186}
2187def TBZImm32_63Operand : AsmOperandClass {
2188  let Name = "Imm32_63";
2189  let PredicateMethod = "isImmInRange<32,63>";
2190  let DiagnosticType = "InvalidImm0_63";
2191  let RenderMethod = "addImmOperands";
2192}
2193
2194class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
2195  return (((uint32_t)Imm) < 32);
2196}]> {
2197  let ParserMatchClass = matcher;
2198}
2199
2200def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
2201def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
2202
2203def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
2204  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
2205}]> {
2206  let ParserMatchClass = TBZImm32_63Operand;
2207}
2208
2209class BaseTestBranch<RegisterClass regtype, Operand immtype,
2210                     bit op, string asm, SDNode node>
2211    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
2212       asm, "\t$Rt, $bit_off, $target", "",
2213       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
2214      Sched<[WriteBr]> {
2215  let isBranch = 1;
2216  let isTerminator = 1;
2217
2218  bits<5> Rt;
2219  bits<6> bit_off;
2220  bits<14> target;
2221
2222  let Inst{30-25} = 0b011011;
2223  let Inst{24}    = op;
2224  let Inst{23-19} = bit_off{4-0};
2225  let Inst{18-5}  = target;
2226  let Inst{4-0}   = Rt;
2227
2228  let DecoderMethod = "DecodeTestAndBranch";
2229}
2230
2231multiclass TestBranch<bit op, string asm, SDNode node> {
2232  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
2233    let Inst{31} = 0;
2234  }
2235
2236  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
2237    let Inst{31} = 1;
2238  }
2239
2240  // Alias X-reg with 0-31 imm to W-Reg.
2241  def : InstAlias<asm # "\t$Rd, $imm, $target",
2242                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
2243                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
2244  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
2245            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
2246            tbz_imm0_31_diag:$imm, bb:$target)>;
2247}
2248
2249//---
2250// Unconditional branch (immediate) instructions.
2251//---
2252def am_b_target : Operand<OtherVT> {
2253  let EncoderMethod = "getBranchTargetOpValue";
2254  let PrintMethod = "printAlignedLabel";
2255  let ParserMatchClass = BranchTarget26Operand;
2256  let OperandType = "OPERAND_PCREL";
2257}
2258def am_bl_target : Operand<i64> {
2259  let EncoderMethod = "getBranchTargetOpValue";
2260  let PrintMethod = "printAlignedLabel";
2261  let ParserMatchClass = BranchTarget26Operand;
2262  let OperandType = "OPERAND_PCREL";
2263}
2264
2265class BImm<bit op, dag iops, string asm, list<dag> pattern>
2266    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
2267  bits<26> addr;
2268  let Inst{31}    = op;
2269  let Inst{30-26} = 0b00101;
2270  let Inst{25-0}  = addr;
2271
2272  let DecoderMethod = "DecodeUnconditionalBranch";
2273}
2274
2275class BranchImm<bit op, string asm, list<dag> pattern>
2276    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2277class CallImm<bit op, string asm, list<dag> pattern>
2278    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2279
2280//---
2281// Basic one-operand data processing instructions.
2282//---
2283
2284let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2285class BaseOneOperandData<bit sf, bit S, bits<5> opc2, bits<6> opc,
2286                         RegisterClass regtype, string asm,
2287                         SDPatternOperator node>
2288  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2289      [(set regtype:$Rd, (node regtype:$Rn))]>,
2290    Sched<[WriteI, ReadI]> {
2291  bits<5> Rd;
2292  bits<5> Rn;
2293
2294  let Inst{31} = sf;
2295  let Inst{30} = 0b1;
2296  let Inst{29} = S;
2297  let Inst{28-21} = 0b11010110;
2298  let Inst{20-16} = opc2;
2299  let Inst{15-10} = opc;
2300  let Inst{9-5}   = Rn;
2301  let Inst{4-0}   = Rd;
2302}
2303
2304let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2305multiclass OneOperandData<bits<6> opc, string asm,
2306                          SDPatternOperator node = null_frag> {
2307  def Wr : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2308
2309  def Xr : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2310}
2311
2312class OneWRegData<bits<6> opc, string asm, SDPatternOperator node>
2313    : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2314
2315class OneXRegData<bits<6> opc, string asm, SDPatternOperator node>
2316    : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2317
2318class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2319                      SDPatternOperator op>
2320  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2321      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2322    Sched<[WriteI, ReadI]> {
2323  bits<5> Rd;
2324  bits<5> Rn;
2325  let Inst{31-15} = 0b11011010110000010;
2326  let Inst{14-12} = opcode_prefix;
2327  let Inst{11-10} = opcode;
2328  let Inst{9-5} = Rn;
2329  let Inst{4-0} = Rd;
2330}
2331
2332class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2333                   SDPatternOperator op>
2334  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2335      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2336    Sched<[]> {
2337  bits<5> Rd;
2338  let Inst{31-15} = 0b11011010110000010;
2339  let Inst{14-12} = opcode_prefix;
2340  let Inst{11-10} = opcode;
2341  let Inst{9-5} = 0b11111;
2342  let Inst{4-0} = Rd;
2343}
2344
2345class SignAuthTwoOperand<bits<4> opc, string asm,
2346                         SDPatternOperator OpNode>
2347  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2348      asm, "\t$Rd, $Rn, $Rm", "",
2349      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2350    Sched<[WriteI, ReadI, ReadI]> {
2351  bits<5> Rd;
2352  bits<5> Rn;
2353  bits<5> Rm;
2354  let Inst{31-21} = 0b10011010110;
2355  let Inst{20-16} = Rm;
2356  let Inst{15-14} = 0b00;
2357  let Inst{13-10} = opc;
2358  let Inst{9-5}   = Rn;
2359  let Inst{4-0}   = Rd;
2360}
2361
2362class ClearAuth<bits<1> data, string asm>
2363  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2364  bits<5> Rd;
2365  let Inst{31-11} = 0b110110101100000101000;
2366  let Inst{10} = data;
2367  let Inst{9-5} = 0b11111;
2368  let Inst{4-0} = Rd;
2369}
2370
2371// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2372class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2373    : I<(outs), iops, asm, ops, "", []>,
2374      Sched<[WriteI, ReadI, ReadI]> {
2375  let Uses = [NZCV];
2376  let Defs = [NZCV];
2377  bits<5> Rn;
2378  let Inst{31}    = sf;
2379  let Inst{30-15} = 0b0111010000000000;
2380  let Inst{14}    = sz;
2381  let Inst{13-10} = 0b0010;
2382  let Inst{9-5}   = Rn;
2383  let Inst{4-0}   = 0b01101;
2384}
2385
2386class FlagRotate<dag iops, string asm, string ops>
2387    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2388  bits<6> imm;
2389  bits<4> mask;
2390  let Inst{20-15} = imm;
2391  let Inst{13-10} = 0b0001;
2392  let Inst{4}     = 0b0;
2393  let Inst{3-0}   = mask;
2394}
2395
2396//---
2397// Basic two-operand data processing instructions.
2398//---
2399class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2400                          list<dag> pattern>
2401    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2402        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2403      Sched<[WriteI, ReadI, ReadI]> {
2404  let Uses = [NZCV];
2405  bits<5> Rd;
2406  bits<5> Rn;
2407  bits<5> Rm;
2408  let Inst{30}    = isSub;
2409  let Inst{28-21} = 0b11010000;
2410  let Inst{20-16} = Rm;
2411  let Inst{15-10} = 0;
2412  let Inst{9-5}   = Rn;
2413  let Inst{4-0}   = Rd;
2414}
2415
2416class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2417                      SDNode OpNode>
2418    : BaseBaseAddSubCarry<isSub, regtype, asm,
2419        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2420
2421class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2422                              SDNode OpNode>
2423    : BaseBaseAddSubCarry<isSub, regtype, asm,
2424        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2425         (implicit NZCV)]> {
2426  let Defs = [NZCV];
2427}
2428
2429multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2430                       SDNode OpNode, SDNode OpNode_setflags> {
2431  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2432    let Inst{31} = 0;
2433    let Inst{29} = 0;
2434  }
2435  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2436    let Inst{31} = 1;
2437    let Inst{29} = 0;
2438  }
2439
2440  // Sets flags.
2441  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2442                                    OpNode_setflags> {
2443    let Inst{31} = 0;
2444    let Inst{29} = 1;
2445  }
2446  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2447                                    OpNode_setflags> {
2448    let Inst{31} = 1;
2449    let Inst{29} = 1;
2450  }
2451}
2452
2453class BaseTwoOperandRegReg<bit sf, bit S, bits<6> opc, RegisterClass regtype,
2454                           string asm, SDPatternOperator OpNode,
2455                           RegisterClass in1regtype = regtype,
2456                           RegisterClass in2regtype = regtype>
2457  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2458      asm, "\t$Rd, $Rn, $Rm", "",
2459      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2460  bits<5> Rd;
2461  bits<5> Rn;
2462  bits<5> Rm;
2463  let Inst{31}    = sf;
2464  let Inst{30}    = 0b0;
2465  let Inst{29}    = S;
2466  let Inst{28-21} = 0b11010110;
2467  let Inst{20-16} = Rm;
2468  let Inst{15-10} = opc;
2469  let Inst{9-5}   = Rn;
2470  let Inst{4-0}   = Rd;
2471}
2472
2473class BaseDiv<bit size, bit isSigned, RegisterClass regtype, string asm,
2474              SDPatternOperator OpNode>
2475    : BaseTwoOperandRegReg<size, 0b0, {0,0,0,0,1,?}, regtype, asm, OpNode> {
2476  let Inst{10}    = isSigned;
2477}
2478
2479multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2480  def Wr : BaseDiv<0b0, isSigned, GPR32, asm, OpNode>,
2481           Sched<[WriteID32, ReadID, ReadID]>;
2482
2483  def Xr : BaseDiv<0b1, isSigned, GPR64, asm, OpNode>,
2484           Sched<[WriteID64, ReadID, ReadID]>;
2485}
2486
2487class BaseShift<bit size, bits<2> shift_type, RegisterClass regtype, string asm,
2488                SDPatternOperator OpNode = null_frag>
2489  : BaseTwoOperandRegReg<size, 0b0, {0,0,1,0,?,?}, regtype, asm, OpNode>,
2490    Sched<[WriteIS, ReadI]> {
2491  let Inst{11-10} = shift_type;
2492}
2493
2494multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2495  def Wr : BaseShift<0b0, shift_type, GPR32, asm>;
2496
2497  def Xr : BaseShift<0b1, shift_type, GPR64, asm, OpNode>;
2498
2499  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2500            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2501                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2502
2503  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2504            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2505
2506  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2507            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2508
2509  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2510            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2511
2512  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2513            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2514                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2515
2516  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2517            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2518                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2519}
2520
2521class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2522    : InstAlias<asm#"\t$dst, $src1, $src2",
2523                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2524
2525class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2526                       RegisterClass addtype, string asm,
2527                       list<dag> pattern>
2528  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2529      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2530  bits<5> Rd;
2531  bits<5> Rn;
2532  bits<5> Rm;
2533  bits<5> Ra;
2534  let Inst{30-24} = 0b0011011;
2535  let Inst{23-21} = opc;
2536  let Inst{20-16} = Rm;
2537  let Inst{15}    = isSub;
2538  let Inst{14-10} = Ra;
2539  let Inst{9-5}   = Rn;
2540  let Inst{4-0}   = Rd;
2541}
2542
2543multiclass MulAccum<bit isSub, string asm> {
2544  // MADD/MSUB generation is decided by MachineCombiner.cpp
2545  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2546      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2547    let Inst{31} = 0;
2548  }
2549
2550  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2551      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2552    let Inst{31} = 1;
2553  }
2554}
2555
2556class WideMulAccum<bit isSub, bits<3> opc, string asm,
2557                   SDNode AccNode, SDNode ExtNode>
2558  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2559    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2560                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2561    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2562  let Inst{31} = 1;
2563}
2564
2565class MulHi<bits<3> opc, string asm, SDNode OpNode>
2566  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2567      asm, "\t$Rd, $Rn, $Rm", "",
2568      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2569    Sched<[WriteIM64, ReadIM, ReadIM]> {
2570  bits<5> Rd;
2571  bits<5> Rn;
2572  bits<5> Rm;
2573  let Inst{31-24} = 0b10011011;
2574  let Inst{23-21} = opc;
2575  let Inst{20-16} = Rm;
2576  let Inst{15}    = 0;
2577  let Inst{9-5}   = Rn;
2578  let Inst{4-0}   = Rd;
2579
2580  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2581  // (i.e. all bits 1) but is ignored by the processor.
2582  let PostEncoderMethod = "fixMulHigh";
2583}
2584
2585class MulAccumWAlias<string asm, Instruction inst>
2586    : InstAlias<asm#"\t$dst, $src1, $src2",
2587                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2588class MulAccumXAlias<string asm, Instruction inst>
2589    : InstAlias<asm#"\t$dst, $src1, $src2",
2590                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2591class WideMulAccumAlias<string asm, Instruction inst>
2592    : InstAlias<asm#"\t$dst, $src1, $src2",
2593                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2594
2595class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2596              SDPatternOperator OpNode, string asm>
2597  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2598      asm, "\t$Rd, $Rn, $Rm", "",
2599      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2600    Sched<[WriteISReg, ReadI, ReadISReg]> {
2601  bits<5> Rd;
2602  bits<5> Rn;
2603  bits<5> Rm;
2604
2605  let Inst{31} = sf;
2606  let Inst{30-21} = 0b0011010110;
2607  let Inst{20-16} = Rm;
2608  let Inst{15-13} = 0b010;
2609  let Inst{12} = C;
2610  let Inst{11-10} = sz;
2611  let Inst{9-5} = Rn;
2612  let Inst{4-0} = Rd;
2613  let Predicates = [HasCRC];
2614}
2615
2616//---
2617// Address generation.
2618//---
2619
2620class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2621    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2622        pattern>,
2623      Sched<[WriteI]> {
2624  bits<5>  Xd;
2625  bits<21> label;
2626  let Inst{31}    = page;
2627  let Inst{30-29} = label{1-0};
2628  let Inst{28-24} = 0b10000;
2629  let Inst{23-5}  = label{20-2};
2630  let Inst{4-0}   = Xd;
2631
2632  let DecoderMethod = "DecodeAdrInstruction";
2633}
2634
2635//---
2636// Move immediate.
2637//---
2638
2639def movimm32_imm : Operand<i32> {
2640  let ParserMatchClass = AsmImmRange<0, 65535>;
2641  let EncoderMethod = "getMoveWideImmOpValue";
2642  let PrintMethod = "printImm";
2643}
2644def movimm32_shift : Operand<i32> {
2645  let PrintMethod = "printShifter";
2646  let ParserMatchClass = MovImm32ShifterOperand;
2647}
2648def movimm64_shift : Operand<i32> {
2649  let PrintMethod = "printShifter";
2650  let ParserMatchClass = MovImm64ShifterOperand;
2651}
2652
2653let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2654class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2655                        string asm>
2656  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2657       asm, "\t$Rd, $imm$shift", "", []>,
2658    Sched<[WriteImm]> {
2659  bits<5> Rd;
2660  bits<16> imm;
2661  bits<6> shift;
2662  let Inst{30-29} = opc;
2663  let Inst{28-23} = 0b100101;
2664  let Inst{22-21} = shift{5-4};
2665  let Inst{20-5}  = imm;
2666  let Inst{4-0}   = Rd;
2667
2668  let DecoderMethod = "DecodeMoveImmInstruction";
2669}
2670
2671multiclass MoveImmediate<bits<2> opc, string asm> {
2672  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2673    let Inst{31} = 0;
2674  }
2675
2676  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2677    let Inst{31} = 1;
2678  }
2679}
2680
2681let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2682class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2683                          string asm>
2684  : I<(outs regtype:$Rd),
2685      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2686       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2687    Sched<[WriteI, ReadI]> {
2688  bits<5> Rd;
2689  bits<16> imm;
2690  bits<6> shift;
2691  let Inst{30-29} = opc;
2692  let Inst{28-23} = 0b100101;
2693  let Inst{22-21} = shift{5-4};
2694  let Inst{20-5}  = imm;
2695  let Inst{4-0}   = Rd;
2696
2697  let DecoderMethod = "DecodeMoveImmInstruction";
2698}
2699
2700multiclass InsertImmediate<bits<2> opc, string asm> {
2701  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2702    let Inst{31} = 0;
2703  }
2704
2705  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2706    let Inst{31} = 1;
2707  }
2708}
2709
2710//---
2711// Add/Subtract
2712//---
2713
2714class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2715                    string asm_inst, string asm_ops,
2716                    dag inputs, dag pattern>
2717    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2718      Sched<[WriteI, ReadI]> {
2719  bits<5>  Rd;
2720  bits<5>  Rn;
2721  let Inst{30}    = isSub;
2722  let Inst{29}    = setFlags;
2723  let Inst{28-24} = 0b10001;
2724  let Inst{9-5}   = Rn;
2725  let Inst{4-0}   = Rd;
2726}
2727
2728class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2729                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2730                     string asm_inst, SDPatternOperator OpNode>
2731    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2732                    (ins srcRegtype:$Rn, immtype:$imm),
2733                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2734  bits<14> imm;
2735  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2736  let Inst{21-10} = imm{11-0};
2737  let DecoderMethod = "DecodeAddSubImmShift";
2738}
2739
2740class BaseAddSubRegPseudo<RegisterClass regtype,
2741                          SDPatternOperator OpNode>
2742    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2743             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2744      Sched<[WriteI, ReadI, ReadI]>;
2745
2746class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2747                     arith_shifted_reg shifted_regtype, string asm,
2748                     SDPatternOperator OpNode>
2749    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
2750        asm, "\t$Rd, $Rn, $Rm_and_shift", "",
2751        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm_and_shift))]>,
2752      Sched<[WriteISReg, ReadI, ReadISReg]> {
2753  bits<5> Rd;
2754  bits<5> Rn;
2755  bits<5> Rm;
2756  bits<8> shift;
2757  let Inst{30}    = isSub;
2758  let Inst{29}    = setFlags;
2759  let Inst{28-24} = 0b01011;
2760  let Inst{23-22} = shift{7-6};
2761  let Inst{21}    = 0;
2762  let Inst{20-16} = Rm;
2763  let Inst{15-10} = shift{5-0};
2764  let Inst{9-5}   = Rn;
2765  let Inst{4-0}   = Rd;
2766
2767  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2768}
2769
2770class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2771                     RegisterClass src1Regtype, Operand src2Regtype,
2772                     string asm, SDPatternOperator OpNode>
2773    : I<(outs dstRegtype:$Rd),
2774        (ins src1Regtype:$Rn, (src2Regtype $Rm, $extend):$Rm_and_extend),
2775        asm, "\t$Rd, $Rn, $Rm_and_extend", "",
2776        [(set dstRegtype:$Rd, (OpNode src1Regtype:$Rn, src2Regtype:$Rm_and_extend))]>,
2777      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2778  bits<5> Rd;
2779  bits<5> Rn;
2780  bits<5> Rm;
2781  bits<6> extend;
2782  let Inst{30}    = isSub;
2783  let Inst{29}    = setFlags;
2784  let Inst{28-24} = 0b01011;
2785  let Inst{23-21} = 0b001;
2786  let Inst{20-16} = Rm;
2787  let Inst{15-13} = extend{5-3};
2788  let Inst{12-10} = extend{2-0};
2789  let Inst{9-5}   = Rn;
2790  let Inst{4-0}   = Rd;
2791
2792  let DecoderMethod = "DecodeAddSubERegInstruction";
2793}
2794
2795let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2796class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2797                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2798                       Operand ext_op, string asm>
2799    : I<(outs dstRegtype:$Rd),
2800        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2801        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2802      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2803  bits<5> Rd;
2804  bits<5> Rn;
2805  bits<5> Rm;
2806  bits<6> ext;
2807  let Inst{30}    = isSub;
2808  let Inst{29}    = setFlags;
2809  let Inst{28-24} = 0b01011;
2810  let Inst{23-21} = 0b001;
2811  let Inst{20-16} = Rm;
2812  let Inst{15}    = ext{5};
2813  let Inst{12-10} = ext{2-0};
2814  let Inst{9-5}   = Rn;
2815  let Inst{4-0}   = Rd;
2816
2817  let DecoderMethod = "DecodeAddSubERegInstruction";
2818}
2819
2820// Aliases for register+register add/subtract.
2821class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2822                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2823                     int shiftExt>
2824    : InstAlias<asm#"\t$dst, $src1, $src2",
2825                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2826                      shiftExt)>;
2827
2828multiclass AddSub<bit isSub, string mnemonic, string alias,
2829                  SDPatternOperator OpNode = null_frag> {
2830  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2831  // Add/Subtract immediate
2832  // Increase the weight of the immediate variant to try to match it before
2833  // the extended register variant.
2834  // We used to match the register variant before the immediate when the
2835  // register argument could be implicitly zero-extended.
2836  let AddedComplexity = 6 in
2837  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2838                           mnemonic, OpNode> {
2839    let Inst{31} = 0;
2840  }
2841  let AddedComplexity = 6 in
2842  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2843                           mnemonic, OpNode> {
2844    let Inst{31} = 1;
2845  }
2846
2847  // Add/Subtract register - Only used for CodeGen
2848  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2849  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2850
2851  // Add/Subtract shifted register
2852  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2853                           OpNode> {
2854    let Inst{31} = 0;
2855  }
2856  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2857                           OpNode> {
2858    let Inst{31} = 1;
2859  }
2860  }
2861
2862  // Add/Subtract extended register
2863  let AddedComplexity = 1, hasSideEffects = 0 in {
2864  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2865                           arith_extended_reg32_i32, mnemonic, OpNode> {
2866    let Inst{31} = 0;
2867  }
2868  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2869                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2870    let Inst{31} = 1;
2871  }
2872  }
2873
2874  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2875                               arith_extendlsl64, mnemonic> {
2876    // UXTX and SXTX only.
2877    let Inst{14-13} = 0b11;
2878    let Inst{31} = 1;
2879  }
2880
2881  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2882  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2883                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2884                      addsub_shifted_imm32_neg:$imm), 0>;
2885  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2886                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2887                       addsub_shifted_imm64_neg:$imm), 0>;
2888
2889  // Register/register aliases with no shift when SP is not used.
2890  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2891                       GPR32, GPR32, GPR32, 0>;
2892  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2893                       GPR64, GPR64, GPR64, 0>;
2894
2895  // Register/register aliases with no shift when either the destination or
2896  // first source register is SP.
2897  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2898                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2899  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2900                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2901  def : AddSubRegAlias<mnemonic,
2902                       !cast<Instruction>(NAME#"Xrx64"),
2903                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2904  def : AddSubRegAlias<mnemonic,
2905                       !cast<Instruction>(NAME#"Xrx64"),
2906                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2907}
2908
2909multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2910                   string alias, string cmpAlias> {
2911  let isCompare = 1, Defs = [NZCV] in {
2912  // Add/Subtract immediate
2913  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2914                           mnemonic, OpNode> {
2915    let Inst{31} = 0;
2916  }
2917  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2918                           mnemonic, OpNode> {
2919    let Inst{31} = 1;
2920  }
2921
2922  // Add/Subtract register
2923  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2924  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2925
2926  // Add/Subtract shifted register
2927  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2928                           OpNode> {
2929    let Inst{31} = 0;
2930  }
2931  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2932                           OpNode> {
2933    let Inst{31} = 1;
2934  }
2935
2936  // Add/Subtract extended register
2937  let AddedComplexity = 1 in {
2938  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2939                           arith_extended_reg32_i32, mnemonic, OpNode> {
2940    let Inst{31} = 0;
2941  }
2942  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2943                           arith_extended_reg32_i64, mnemonic, OpNode> {
2944    let Inst{31} = 1;
2945  }
2946  }
2947
2948  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2949                               arith_extendlsl64, mnemonic> {
2950    // UXTX and SXTX only.
2951    let Inst{14-13} = 0b11;
2952    let Inst{31} = 1;
2953  }
2954  } // Defs = [NZCV]
2955
2956  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2957  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2958                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2959                      addsub_shifted_imm32_neg:$imm), 0>;
2960  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2961                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2962                       addsub_shifted_imm64_neg:$imm), 0>;
2963
2964  // Compare aliases
2965  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2966                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2967  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2968                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2969  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2970                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2971  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2972                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2973  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2974                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2975  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2976                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2977  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2978                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2979
2980  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2981  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2982                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2983  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2984                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2985
2986  // Compare shorthands
2987  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2988                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2989  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2990                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2991  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2992                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2993  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2994                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2995
2996  // Register/register aliases with no shift when SP is not used.
2997  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2998                       GPR32, GPR32, GPR32, 0>;
2999  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
3000                       GPR64, GPR64, GPR64, 0>;
3001
3002  // Register/register aliases with no shift when the first source register
3003  // is SP.
3004  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
3005                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
3006  def : AddSubRegAlias<mnemonic,
3007                       !cast<Instruction>(NAME#"Xrx64"),
3008                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
3009}
3010
3011class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
3012      : BaseAddSubImm<
3013          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
3014          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
3015          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
3016  bits<6> imm6;
3017  bits<4> imm4;
3018  let Inst{31} = 1;
3019  let Inst{23-22} = 0b10;
3020  let Inst{21-16} = imm6;
3021  let Inst{15-14} = 0b00;
3022  let Inst{13-10} = imm4;
3023  let Unpredictable{15-14} = 0b11;
3024}
3025
3026class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
3027      : BaseTwoOperandRegReg<0b1, setsFlags, 0b000000, GPR64, asm_instr, OpNode,
3028                             GPR64sp, GPR64sp>;
3029
3030//---
3031// Extract
3032//---
3033def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
3034                                      SDTCisPtrTy<3>]>;
3035def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
3036
3037class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
3038                     list<dag> patterns>
3039    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
3040         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
3041      Sched<[WriteExtr, ReadExtrHi]> {
3042  bits<5> Rd;
3043  bits<5> Rn;
3044  bits<5> Rm;
3045  bits<6> imm;
3046
3047  let Inst{30-23} = 0b00100111;
3048  let Inst{21}    = 0;
3049  let Inst{20-16} = Rm;
3050  let Inst{15-10} = imm;
3051  let Inst{9-5}   = Rn;
3052  let Inst{4-0}   = Rd;
3053}
3054
3055multiclass ExtractImm<string asm> {
3056  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
3057                      [(set GPR32:$Rd,
3058                        (fshr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
3059    let Inst{31} = 0;
3060    let Inst{22} = 0;
3061    // imm<5> must be zero.
3062    let imm{5}   = 0;
3063  }
3064  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
3065                      [(set GPR64:$Rd,
3066                        (fshr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
3067
3068    let Inst{31} = 1;
3069    let Inst{22} = 1;
3070  }
3071}
3072
3073//---
3074// Bitfield
3075//---
3076
3077let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3078class BaseBitfieldImm<bits<2> opc,
3079                      RegisterClass regtype, Operand imm_type, string asm>
3080    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
3081         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
3082      Sched<[WriteIS, ReadI]> {
3083  bits<5> Rd;
3084  bits<5> Rn;
3085  bits<6> immr;
3086  bits<6> imms;
3087
3088  let Inst{30-29} = opc;
3089  let Inst{28-23} = 0b100110;
3090  let Inst{21-16} = immr;
3091  let Inst{15-10} = imms;
3092  let Inst{9-5}   = Rn;
3093  let Inst{4-0}   = Rd;
3094}
3095
3096multiclass BitfieldImm<bits<2> opc, string asm> {
3097  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
3098    let Inst{31} = 0;
3099    let Inst{22} = 0;
3100    // imms<5> and immr<5> must be zero, else ReservedValue().
3101    let Inst{21} = 0;
3102    let Inst{15} = 0;
3103  }
3104  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
3105    let Inst{31} = 1;
3106    let Inst{22} = 1;
3107  }
3108}
3109
3110let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3111class BaseBitfieldImmWith2RegArgs<bits<2> opc,
3112                      RegisterClass regtype, Operand imm_type, string asm>
3113    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
3114                             imm_type:$imms),
3115         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
3116      Sched<[WriteIS, ReadI]> {
3117  bits<5> Rd;
3118  bits<5> Rn;
3119  bits<6> immr;
3120  bits<6> imms;
3121
3122  let Inst{30-29} = opc;
3123  let Inst{28-23} = 0b100110;
3124  let Inst{21-16} = immr;
3125  let Inst{15-10} = imms;
3126  let Inst{9-5}   = Rn;
3127  let Inst{4-0}   = Rd;
3128}
3129
3130multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
3131  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
3132    let Inst{31} = 0;
3133    let Inst{22} = 0;
3134    // imms<5> and immr<5> must be zero, else ReservedValue().
3135    let Inst{21} = 0;
3136    let Inst{15} = 0;
3137  }
3138  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
3139    let Inst{31} = 1;
3140    let Inst{22} = 1;
3141  }
3142}
3143
3144//---
3145// Logical
3146//---
3147
3148// Logical (immediate)
3149class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
3150                     RegisterClass sregtype, Operand imm_type, string asm,
3151                     list<dag> pattern>
3152    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
3153         asm, "\t$Rd, $Rn, $imm", "", pattern>,
3154      Sched<[WriteI, ReadI]> {
3155  bits<5>  Rd;
3156  bits<5>  Rn;
3157  bits<13> imm;
3158  let Inst{30-29} = opc;
3159  let Inst{28-23} = 0b100100;
3160  let Inst{22}    = imm{12};
3161  let Inst{21-16} = imm{11-6};
3162  let Inst{15-10} = imm{5-0};
3163  let Inst{9-5}   = Rn;
3164  let Inst{4-0}   = Rd;
3165
3166  let DecoderMethod = "DecodeLogicalImmInstruction";
3167}
3168
3169// Logical (shifted register)
3170class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
3171                      logical_shifted_reg shifted_regtype, string asm,
3172                      list<dag> pattern>
3173    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
3174        asm, "\t$Rd, $Rn, $Rm_and_shift", "", pattern>,
3175      Sched<[WriteISReg, ReadI, ReadISReg]> {
3176  bits<5> Rd;
3177  bits<5> Rn;
3178  bits<5> Rm;
3179  bits<8> shift;
3180  let Inst{30-29} = opc;
3181  let Inst{28-24} = 0b01010;
3182  let Inst{23-22} = shift{7-6};
3183  let Inst{21}    = N;
3184  let Inst{20-16} = Rm;
3185  let Inst{15-10} = shift{5-0};
3186  let Inst{9-5}   = Rn;
3187  let Inst{4-0}   = Rd;
3188
3189  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
3190}
3191
3192// Aliases for register+register logical instructions.
3193class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
3194    : InstAlias<asm#"\t$dst, $src1, $src2",
3195                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
3196
3197multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
3198                      string Alias> {
3199  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3200  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
3201                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
3202                                               logical_imm32:$imm))]> {
3203    let Inst{31} = 0;
3204    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3205  }
3206  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3207  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
3208                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
3209                                               logical_imm64:$imm))]> {
3210    let Inst{31} = 1;
3211  }
3212
3213  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3214                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
3215                      logical_imm32_not:$imm), 0>;
3216  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3217                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
3218                       logical_imm64_not:$imm), 0>;
3219}
3220
3221multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
3222                       string Alias> {
3223  let isCompare = 1, Defs = [NZCV] in {
3224  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
3225      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
3226    let Inst{31} = 0;
3227    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3228  }
3229  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
3230      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
3231    let Inst{31} = 1;
3232  }
3233  } // end Defs = [NZCV]
3234
3235  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3236                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
3237                      logical_imm32_not:$imm), 0>;
3238  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3239                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
3240                       logical_imm64_not:$imm), 0>;
3241}
3242
3243class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
3244    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3245             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
3246      Sched<[WriteI, ReadI, ReadI]>;
3247
3248// Split from LogicalImm as not all instructions have both.
3249multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
3250                      SDPatternOperator OpNode, int AddedComplexityVal = 0> {
3251  let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = AddedComplexityVal in {
3252  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3253  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3254  }
3255
3256  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3257                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3258                                                 logical_shifted_reg32:$Rm_and_shift))]> {
3259    let Inst{31} = 0;
3260  }
3261  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3262                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3263                                                 logical_shifted_reg64:$Rm_and_shift))]> {
3264    let Inst{31} = 1;
3265  }
3266
3267  def : LogicalRegAlias<mnemonic,
3268                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3269  def : LogicalRegAlias<mnemonic,
3270                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3271}
3272
3273// Split from LogicalReg to allow setting NZCV Defs
3274multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3275                       SDPatternOperator OpNode = null_frag> {
3276  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3277  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3278  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3279
3280  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3281            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm_and_shift))]> {
3282    let Inst{31} = 0;
3283  }
3284  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3285            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm_and_shift))]> {
3286    let Inst{31} = 1;
3287  }
3288  } // Defs = [NZCV]
3289
3290  def : LogicalRegAlias<mnemonic,
3291                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3292  def : LogicalRegAlias<mnemonic,
3293                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3294}
3295
3296//---
3297// Conditionally set flags
3298//---
3299
3300let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3301class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3302                            string mnemonic, SDNode OpNode>
3303    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3304         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3305         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3306                             (i32 imm:$cond), NZCV))]>,
3307      Sched<[WriteI, ReadI]> {
3308  let Uses = [NZCV];
3309  let Defs = [NZCV];
3310
3311  bits<5> Rn;
3312  bits<5> imm;
3313  bits<4> nzcv;
3314  bits<4> cond;
3315
3316  let Inst{30}    = op;
3317  let Inst{29-21} = 0b111010010;
3318  let Inst{20-16} = imm;
3319  let Inst{15-12} = cond;
3320  let Inst{11-10} = 0b10;
3321  let Inst{9-5}   = Rn;
3322  let Inst{4}     = 0b0;
3323  let Inst{3-0}   = nzcv;
3324}
3325
3326let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3327class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3328                            SDNode OpNode>
3329    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3330         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3331         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3332                             (i32 imm:$cond), NZCV))]>,
3333      Sched<[WriteI, ReadI, ReadI]> {
3334  let Uses = [NZCV];
3335  let Defs = [NZCV];
3336
3337  bits<5> Rn;
3338  bits<5> Rm;
3339  bits<4> nzcv;
3340  bits<4> cond;
3341
3342  let Inst{30}    = op;
3343  let Inst{29-21} = 0b111010010;
3344  let Inst{20-16} = Rm;
3345  let Inst{15-12} = cond;
3346  let Inst{11-10} = 0b00;
3347  let Inst{9-5}   = Rn;
3348  let Inst{4}     = 0b0;
3349  let Inst{3-0}   = nzcv;
3350}
3351
3352multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3353  // immediate operand variants
3354  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3355    let Inst{31} = 0;
3356  }
3357  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3358    let Inst{31} = 1;
3359  }
3360  // register operand variants
3361  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3362    let Inst{31} = 0;
3363  }
3364  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3365    let Inst{31} = 1;
3366  }
3367}
3368
3369//---
3370// Conditional select
3371//---
3372
3373class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3374    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3375         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3376         [(set regtype:$Rd,
3377               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3378      Sched<[WriteI, ReadI, ReadI]> {
3379  let Uses = [NZCV];
3380
3381  bits<5> Rd;
3382  bits<5> Rn;
3383  bits<5> Rm;
3384  bits<4> cond;
3385
3386  let Inst{30}    = op;
3387  let Inst{29-21} = 0b011010100;
3388  let Inst{20-16} = Rm;
3389  let Inst{15-12} = cond;
3390  let Inst{11-10} = op2;
3391  let Inst{9-5}   = Rn;
3392  let Inst{4-0}   = Rd;
3393}
3394
3395multiclass CondSelect<bit op, bits<2> op2, string asm> {
3396  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3397    let Inst{31} = 0;
3398  }
3399  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3400    let Inst{31} = 1;
3401  }
3402}
3403
3404class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3405                       PatFrag frag>
3406    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3407         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3408         [(set regtype:$Rd,
3409               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3410               (i32 imm:$cond), NZCV))]>,
3411      Sched<[WriteI, ReadI, ReadI]> {
3412  let Uses = [NZCV];
3413
3414  bits<5> Rd;
3415  bits<5> Rn;
3416  bits<5> Rm;
3417  bits<4> cond;
3418
3419  let Inst{30}    = op;
3420  let Inst{29-21} = 0b011010100;
3421  let Inst{20-16} = Rm;
3422  let Inst{15-12} = cond;
3423  let Inst{11-10} = op2;
3424  let Inst{9-5}   = Rn;
3425  let Inst{4-0}   = Rd;
3426}
3427
3428def inv_cond_XFORM : SDNodeXForm<imm, [{
3429  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3430  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3431                                   MVT::i32);
3432}]>;
3433
3434multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3435  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3436    let Inst{31} = 0;
3437  }
3438  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3439    let Inst{31} = 1;
3440  }
3441
3442  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3443            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3444                                           (inv_cond_XFORM imm:$cond))>;
3445
3446  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3447            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3448                                           (inv_cond_XFORM imm:$cond))>;
3449}
3450
3451//---
3452// Special Mask Value
3453//---
3454def maski8_or_more : Operand<i32>,
3455  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3456}
3457def maski16_or_more : Operand<i32>,
3458  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3459}
3460
3461
3462//---
3463// Load/store
3464//---
3465
3466// (unsigned immediate)
3467// Indexed for 8-bit registers. offset is in range [0,4095].
3468def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3469def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3470def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3471def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3472def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3473
3474// (unsigned immediate)
3475// Indexed for 8-bit registers. offset is in range [0,63].
3476def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3477def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3478def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3479def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3480
3481def gi_am_indexed8 :
3482    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3483    GIComplexPatternEquiv<am_indexed8>;
3484def gi_am_indexed16 :
3485    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3486    GIComplexPatternEquiv<am_indexed16>;
3487def gi_am_indexed32 :
3488    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3489    GIComplexPatternEquiv<am_indexed32>;
3490def gi_am_indexed64 :
3491    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3492    GIComplexPatternEquiv<am_indexed64>;
3493def gi_am_indexed128 :
3494    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3495    GIComplexPatternEquiv<am_indexed128>;
3496
3497class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3498  let Name = "UImm12Offset" # Scale;
3499  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3500  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3501  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3502}
3503
3504def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3505def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3506def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3507def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3508def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3509
3510class uimm12_scaled<int Scale> : Operand<i64> {
3511  let ParserMatchClass
3512   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3513  let EncoderMethod
3514   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3515  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3516}
3517
3518def uimm12s1 : uimm12_scaled<1>;
3519def uimm12s2 : uimm12_scaled<2>;
3520def uimm12s4 : uimm12_scaled<4>;
3521def uimm12s8 : uimm12_scaled<8>;
3522def uimm12s16 : uimm12_scaled<16>;
3523
3524class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3525                      string asm, list<dag> pattern>
3526    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3527  bits<5> Rt;
3528
3529  bits<5> Rn;
3530  bits<12> offset;
3531
3532  let Inst{31-30} = sz;
3533  let Inst{29-27} = 0b111;
3534  let Inst{26}    = V;
3535  let Inst{25-24} = 0b01;
3536  let Inst{23-22} = opc;
3537  let Inst{21-10} = offset;
3538  let Inst{9-5}   = Rn;
3539  let Inst{4-0}   = Rt;
3540
3541  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3542}
3543
3544multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3545                  Operand indextype, string asm, list<dag> pattern> {
3546  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3547  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3548                           (ins GPR64sp:$Rn, indextype:$offset),
3549                           asm, pattern>,
3550           Sched<[WriteLD]>;
3551
3552  def : InstAlias<asm # "\t$Rt, [$Rn]",
3553                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3554}
3555
3556multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3557             Operand indextype, string asm, list<dag> pattern> {
3558  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3559  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3560                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3561                           asm, pattern>,
3562           Sched<[WriteST]>;
3563
3564  def : InstAlias<asm # "\t$Rt, [$Rn]",
3565                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3566}
3567
3568// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3569// substitute zero-registers automatically.
3570//
3571// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3572//       into StoreUI.
3573multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3574             Operand indextype, string asm, list<dag> pattern> {
3575  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3576  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3577                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3578                           asm, pattern>,
3579           Sched<[WriteST]>;
3580
3581  def : InstAlias<asm # "\t$Rt, [$Rn]",
3582                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3583}
3584
3585def PrefetchOperand : AsmOperandClass {
3586  let Name = "Prefetch";
3587  let ParserMethod = "tryParsePrefetch";
3588}
3589def prfop : Operand<i32> {
3590  let PrintMethod = "printPrefetchOp";
3591  let ParserMatchClass = PrefetchOperand;
3592}
3593
3594let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3595class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3596    : BaseLoadStoreUI<sz, V, opc,
3597                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3598                      asm, pat>,
3599      Sched<[WriteLD]>;
3600
3601//---
3602// Load literal
3603//---
3604
3605// Load literal address: 19-bit immediate. The low two bits of the target
3606// offset are implied zero and so are not part of the immediate.
3607def am_ldrlit : Operand<iPTR> {
3608  let EncoderMethod = "getLoadLiteralOpValue";
3609  let DecoderMethod = "DecodePCRelLabel19";
3610  let PrintMethod = "printAlignedLabel";
3611  let ParserMatchClass = PCRelLabel19Operand;
3612  let OperandType = "OPERAND_PCREL";
3613}
3614
3615let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3616class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3617    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3618        asm, "\t$Rt, $label", "", pat>,
3619      Sched<[WriteLD]> {
3620  bits<5> Rt;
3621  bits<19> label;
3622  let Inst{31-30} = opc;
3623  let Inst{29-27} = 0b011;
3624  let Inst{26}    = V;
3625  let Inst{25-24} = 0b00;
3626  let Inst{23-5}  = label;
3627  let Inst{4-0}   = Rt;
3628}
3629
3630let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3631class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3632    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3633        asm, "\t$Rt, $label", "", pat>,
3634      Sched<[WriteLD]> {
3635  bits<5> Rt;
3636  bits<19> label;
3637  let Inst{31-30} = opc;
3638  let Inst{29-27} = 0b011;
3639  let Inst{26}    = V;
3640  let Inst{25-24} = 0b00;
3641  let Inst{23-5}  = label;
3642  let Inst{4-0}   = Rt;
3643}
3644
3645//---
3646// Load/store register offset
3647//---
3648
3649def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3650def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3651def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3652def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3653def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3654
3655def gi_ro_Xindexed8 :
3656    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3657    GIComplexPatternEquiv<ro_Xindexed8>;
3658def gi_ro_Xindexed16 :
3659    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3660    GIComplexPatternEquiv<ro_Xindexed16>;
3661def gi_ro_Xindexed32 :
3662    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3663    GIComplexPatternEquiv<ro_Xindexed32>;
3664def gi_ro_Xindexed64 :
3665    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3666    GIComplexPatternEquiv<ro_Xindexed64>;
3667def gi_ro_Xindexed128 :
3668    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3669    GIComplexPatternEquiv<ro_Xindexed128>;
3670
3671def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3672def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3673def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3674def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3675def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3676
3677def gi_ro_Windexed8 :
3678    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3679    GIComplexPatternEquiv<ro_Windexed8>;
3680def gi_ro_Windexed16 :
3681    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3682    GIComplexPatternEquiv<ro_Windexed16>;
3683def gi_ro_Windexed32 :
3684    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3685    GIComplexPatternEquiv<ro_Windexed32>;
3686def gi_ro_Windexed64 :
3687    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3688    GIComplexPatternEquiv<ro_Windexed64>;
3689def gi_ro_Windexed128 :
3690    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3691    GIComplexPatternEquiv<ro_Windexed128>;
3692
3693class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3694  let Name = "Mem" # Reg # "Extend" # Width;
3695  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3696  let RenderMethod = "addMemExtendOperands";
3697  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3698}
3699
3700def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3701  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3702  // the trivial shift.
3703  let RenderMethod = "addMemExtend8Operands";
3704}
3705def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3706def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3707def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3708def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3709
3710def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3711  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3712  // the trivial shift.
3713  let RenderMethod = "addMemExtend8Operands";
3714}
3715def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3716def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3717def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3718def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3719
3720class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3721        : Operand<i32> {
3722  let ParserMatchClass = ParserClass;
3723  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3724  let DecoderMethod = "DecodeMemExtend";
3725  let EncoderMethod = "getMemExtendOpValue";
3726  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3727}
3728
3729def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3730def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3731def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3732def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3733def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3734
3735def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3736def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3737def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3738def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3739def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3740
3741class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3742                  Operand wextend, Operand xextend>  {
3743  // CodeGen-level pattern covering the entire addressing mode.
3744  ComplexPattern Wpat = windex;
3745  ComplexPattern Xpat = xindex;
3746
3747  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3748  Operand Wext = wextend;
3749  Operand Xext = xextend;
3750}
3751
3752def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3753def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3754def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3755def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3756def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3757                       ro_Xextend128>;
3758
3759class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3760                   dag outs, list<dag> pat>
3761    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3762  bits<5> Rt;
3763  bits<5> Rn;
3764  bits<5> Rm;
3765  bits<2> extend;
3766  let Inst{31-30} = sz;
3767  let Inst{29-27} = 0b111;
3768  let Inst{26}    = V;
3769  let Inst{25-24} = 0b00;
3770  let Inst{23-22} = opc;
3771  let Inst{21}    = 1;
3772  let Inst{20-16} = Rm;
3773  let Inst{15}    = extend{1}; // sign extend Rm?
3774  let Inst{14}    = 1;
3775  let Inst{12}    = extend{0}; // do shift?
3776  let Inst{11-10} = 0b10;
3777  let Inst{9-5}   = Rn;
3778  let Inst{4-0}   = Rt;
3779}
3780
3781class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3782  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3783              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3784
3785multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3786                   string asm, ValueType Ty, SDPatternOperator loadop> {
3787  let AddedComplexity = 10 in
3788  def roW : LoadStore8RO<sz, V, opc, asm,
3789                 (outs regtype:$Rt),
3790                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3791                 [(set (Ty regtype:$Rt),
3792                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3793                                             ro_Wextend8:$extend)))]>,
3794           Sched<[WriteLDIdx, ReadAdrBase]> {
3795    let Inst{13} = 0b0;
3796  }
3797
3798  let AddedComplexity = 10 in
3799  def roX : LoadStore8RO<sz, V, opc, asm,
3800                 (outs regtype:$Rt),
3801                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3802                 [(set (Ty regtype:$Rt),
3803                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3804                                             ro_Xextend8:$extend)))]>,
3805           Sched<[WriteLDIdx, ReadAdrBase]> {
3806    let Inst{13} = 0b1;
3807  }
3808
3809  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3810}
3811
3812multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3813                    string asm, ValueType Ty, SDPatternOperator storeop> {
3814  let AddedComplexity = 10 in
3815  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3816                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3817                 [(storeop (Ty regtype:$Rt),
3818                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3819                                         ro_Wextend8:$extend))]>,
3820            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3821    let Inst{13} = 0b0;
3822  }
3823
3824  let AddedComplexity = 10 in
3825  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3826                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3827                 [(storeop (Ty regtype:$Rt),
3828                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3829                                         ro_Xextend8:$extend))]>,
3830            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3831    let Inst{13} = 0b1;
3832  }
3833
3834  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3835}
3836
3837class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3838                    dag outs, list<dag> pat>
3839    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3840  bits<5> Rt;
3841  bits<5> Rn;
3842  bits<5> Rm;
3843  bits<2> extend;
3844  let Inst{31-30} = sz;
3845  let Inst{29-27} = 0b111;
3846  let Inst{26}    = V;
3847  let Inst{25-24} = 0b00;
3848  let Inst{23-22} = opc;
3849  let Inst{21}    = 1;
3850  let Inst{20-16} = Rm;
3851  let Inst{15}    = extend{1}; // sign extend Rm?
3852  let Inst{14}    = 1;
3853  let Inst{12}    = extend{0}; // do shift?
3854  let Inst{11-10} = 0b10;
3855  let Inst{9-5}   = Rn;
3856  let Inst{4-0}   = Rt;
3857}
3858
3859multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3860                    string asm, ValueType Ty, SDPatternOperator loadop> {
3861  let AddedComplexity = 10 in
3862  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3863                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3864                 [(set (Ty regtype:$Rt),
3865                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3866                                              ro_Wextend16:$extend)))]>,
3867            Sched<[WriteLDIdx, ReadAdrBase]> {
3868    let Inst{13} = 0b0;
3869  }
3870
3871  let AddedComplexity = 10 in
3872  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3873                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3874                 [(set (Ty regtype:$Rt),
3875                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3876                                             ro_Xextend16:$extend)))]>,
3877            Sched<[WriteLDIdx, ReadAdrBase]> {
3878    let Inst{13} = 0b1;
3879  }
3880
3881  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3882}
3883
3884multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3885                     string asm, ValueType Ty, SDPatternOperator storeop> {
3886  let AddedComplexity = 10 in
3887  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3888                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3889                [(storeop (Ty regtype:$Rt),
3890                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3891                                         ro_Wextend16:$extend))]>,
3892           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3893    let Inst{13} = 0b0;
3894  }
3895
3896  let AddedComplexity = 10 in
3897  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3898                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3899                [(storeop (Ty regtype:$Rt),
3900                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3901                                         ro_Xextend16:$extend))]>,
3902           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3903    let Inst{13} = 0b1;
3904  }
3905
3906  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3907}
3908
3909class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3910                    dag outs, list<dag> pat>
3911    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3912  bits<5> Rt;
3913  bits<5> Rn;
3914  bits<5> Rm;
3915  bits<2> extend;
3916  let Inst{31-30} = sz;
3917  let Inst{29-27} = 0b111;
3918  let Inst{26}    = V;
3919  let Inst{25-24} = 0b00;
3920  let Inst{23-22} = opc;
3921  let Inst{21}    = 1;
3922  let Inst{20-16} = Rm;
3923  let Inst{15}    = extend{1}; // sign extend Rm?
3924  let Inst{14}    = 1;
3925  let Inst{12}    = extend{0}; // do shift?
3926  let Inst{11-10} = 0b10;
3927  let Inst{9-5}   = Rn;
3928  let Inst{4-0}   = Rt;
3929}
3930
3931multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3932                    string asm, ValueType Ty, SDPatternOperator loadop> {
3933  let AddedComplexity = 10 in
3934  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3935                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3936                 [(set (Ty regtype:$Rt),
3937                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3938                                              ro_Wextend32:$extend)))]>,
3939           Sched<[WriteLDIdx, ReadAdrBase]> {
3940    let Inst{13} = 0b0;
3941  }
3942
3943  let AddedComplexity = 10 in
3944  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3945                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3946                 [(set (Ty regtype:$Rt),
3947                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3948                                              ro_Xextend32:$extend)))]>,
3949           Sched<[WriteLDIdx, ReadAdrBase]> {
3950    let Inst{13} = 0b1;
3951  }
3952
3953  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3954}
3955
3956multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3957                     string asm, ValueType Ty, SDPatternOperator storeop> {
3958  let AddedComplexity = 10 in
3959  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3960                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3961                [(storeop (Ty regtype:$Rt),
3962                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3963                                         ro_Wextend32:$extend))]>,
3964            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3965    let Inst{13} = 0b0;
3966  }
3967
3968  let AddedComplexity = 10 in
3969  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3970                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3971                [(storeop (Ty regtype:$Rt),
3972                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3973                                        ro_Xextend32:$extend))]>,
3974            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3975    let Inst{13} = 0b1;
3976  }
3977
3978  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3979}
3980
3981class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3982                    dag outs, list<dag> pat>
3983    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3984  bits<5> Rt;
3985  bits<5> Rn;
3986  bits<5> Rm;
3987  bits<2> extend;
3988  let Inst{31-30} = sz;
3989  let Inst{29-27} = 0b111;
3990  let Inst{26}    = V;
3991  let Inst{25-24} = 0b00;
3992  let Inst{23-22} = opc;
3993  let Inst{21}    = 1;
3994  let Inst{20-16} = Rm;
3995  let Inst{15}    = extend{1}; // sign extend Rm?
3996  let Inst{14}    = 1;
3997  let Inst{12}    = extend{0}; // do shift?
3998  let Inst{11-10} = 0b10;
3999  let Inst{9-5}   = Rn;
4000  let Inst{4-0}   = Rt;
4001}
4002
4003multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4004                    string asm, ValueType Ty, SDPatternOperator loadop> {
4005  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4006  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4007                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4008                [(set (Ty regtype:$Rt),
4009                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4010                                             ro_Wextend64:$extend)))]>,
4011           Sched<[WriteLDIdx, ReadAdrBase]> {
4012    let Inst{13} = 0b0;
4013  }
4014
4015  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4016  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4017                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4018                 [(set (Ty regtype:$Rt),
4019                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4020                                              ro_Xextend64:$extend)))]>,
4021           Sched<[WriteLDIdx, ReadAdrBase]> {
4022    let Inst{13} = 0b1;
4023  }
4024
4025  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4026}
4027
4028multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4029                     string asm, ValueType Ty, SDPatternOperator storeop> {
4030  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4031  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
4032                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4033                [(storeop (Ty regtype:$Rt),
4034                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4035                                         ro_Wextend64:$extend))]>,
4036            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4037    let Inst{13} = 0b0;
4038  }
4039
4040  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4041  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
4042                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4043                [(storeop (Ty regtype:$Rt),
4044                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4045                                         ro_Xextend64:$extend))]>,
4046            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4047    let Inst{13} = 0b1;
4048  }
4049
4050  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4051}
4052
4053class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4054                     dag outs, list<dag> pat>
4055    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4056  bits<5> Rt;
4057  bits<5> Rn;
4058  bits<5> Rm;
4059  bits<2> extend;
4060  let Inst{31-30} = sz;
4061  let Inst{29-27} = 0b111;
4062  let Inst{26}    = V;
4063  let Inst{25-24} = 0b00;
4064  let Inst{23-22} = opc;
4065  let Inst{21}    = 1;
4066  let Inst{20-16} = Rm;
4067  let Inst{15}    = extend{1}; // sign extend Rm?
4068  let Inst{14}    = 1;
4069  let Inst{12}    = extend{0}; // do shift?
4070  let Inst{11-10} = 0b10;
4071  let Inst{9-5}   = Rn;
4072  let Inst{4-0}   = Rt;
4073}
4074
4075multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4076                     string asm, ValueType Ty, SDPatternOperator loadop> {
4077  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4078  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4079                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4080                 [(set (Ty regtype:$Rt),
4081                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
4082                                               ro_Wextend128:$extend)))]>,
4083            Sched<[WriteLDIdx, ReadAdrBase]> {
4084    let Inst{13} = 0b0;
4085  }
4086
4087  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4088  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4089                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4090                 [(set (Ty regtype:$Rt),
4091                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
4092                                               ro_Xextend128:$extend)))]>,
4093            Sched<[WriteLDIdx, ReadAdrBase]> {
4094    let Inst{13} = 0b1;
4095  }
4096
4097  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4098}
4099
4100multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4101                      string asm> {
4102  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4103  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
4104               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4105                []>,
4106            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4107    let Inst{13} = 0b0;
4108  }
4109
4110  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4111  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
4112               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4113                []>,
4114            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4115    let Inst{13} = 0b1;
4116  }
4117
4118  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4119}
4120
4121let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4122class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
4123                     string asm, list<dag> pat>
4124    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
4125      Sched<[WriteLD]> {
4126  bits<5> Rt;
4127  bits<5> Rn;
4128  bits<5> Rm;
4129  bits<2> extend;
4130  let Inst{31-30} = sz;
4131  let Inst{29-27} = 0b111;
4132  let Inst{26}    = V;
4133  let Inst{25-24} = 0b00;
4134  let Inst{23-22} = opc;
4135  let Inst{21}    = 1;
4136  let Inst{20-16} = Rm;
4137  let Inst{15}    = extend{1}; // sign extend Rm?
4138  let Inst{14}    = 1;
4139  let Inst{12}    = extend{0}; // do shift?
4140  let Inst{11-10} = 0b10;
4141  let Inst{9-5}   = Rn;
4142  let Inst{4-0}   = Rt;
4143  let DecoderMethod = "DecodePRFMRegInstruction";
4144  // PRFM (reg) aliases with RPRFM added to the base A64 instruction set. When
4145  // the decoder method returns Fail, the decoder should attempt to decode the
4146  // instruction as RPRFM.
4147  let hasCompleteDecoder = 0;
4148}
4149
4150multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
4151  def roW : BasePrefetchRO<sz, V, opc, (outs),
4152                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4153                asm, [(AArch64Prefetch timm:$Rt,
4154                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4155                                                    ro_Wextend64:$extend))]> {
4156    let Inst{13} = 0b0;
4157  }
4158
4159  def roX : BasePrefetchRO<sz, V, opc, (outs),
4160                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4161                asm,  [(AArch64Prefetch timm:$Rt,
4162                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4163                                                     ro_Xextend64:$extend))]> {
4164    let Inst{13} = 0b1;
4165  }
4166
4167  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
4168               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
4169                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
4170}
4171
4172//---
4173// Load/store unscaled immediate
4174//---
4175
4176def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
4177def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
4178def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
4179def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
4180def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
4181
4182def gi_am_unscaled8 :
4183    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
4184    GIComplexPatternEquiv<am_unscaled8>;
4185def gi_am_unscaled16 :
4186    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
4187    GIComplexPatternEquiv<am_unscaled16>;
4188def gi_am_unscaled32 :
4189    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
4190    GIComplexPatternEquiv<am_unscaled32>;
4191def gi_am_unscaled64 :
4192    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
4193    GIComplexPatternEquiv<am_unscaled64>;
4194def gi_am_unscaled128 :
4195    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
4196    GIComplexPatternEquiv<am_unscaled128>;
4197
4198
4199class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4200                           string asm, list<dag> pattern>
4201    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
4202  bits<5> Rt;
4203  bits<5> Rn;
4204  bits<9> offset;
4205  let Inst{31-30} = sz;
4206  let Inst{29-27} = 0b111;
4207  let Inst{26}    = V;
4208  let Inst{25-24} = 0b00;
4209  let Inst{23-22} = opc;
4210  let Inst{21}    = 0;
4211  let Inst{20-12} = offset;
4212  let Inst{11-10} = 0b00;
4213  let Inst{9-5}   = Rn;
4214  let Inst{4-0}   = Rt;
4215
4216  let DecoderMethod = "DecodeSignedLdStInstruction";
4217}
4218
4219// Armv8.4 LDAPR & STLR with Immediate Offset instruction
4220multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4221                              DAGOperand regtype > {
4222  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
4223                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
4224          Sched<[WriteST]> {
4225    let Inst{29} = 0;
4226    let Inst{24} = 1;
4227  }
4228  def : InstAlias<asm # "\t$Rt, [$Rn]",
4229                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4230}
4231
4232multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4233                               DAGOperand regtype > {
4234  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
4235                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4236                               asm, []>,
4237          Sched<[WriteST]> {
4238    let Inst{29} = 0;
4239    let Inst{24} = 1;
4240  }
4241  def : InstAlias<asm # "\t$Rt, [$Rn]",
4242                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4243}
4244
4245multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4246                   string asm, list<dag> pattern> {
4247  let AddedComplexity = 1 in // try this before LoadUI
4248  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
4249                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
4250          Sched<[WriteLD]>;
4251
4252  def : InstAlias<asm # "\t$Rt, [$Rn]",
4253                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4254}
4255
4256multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4257                         string asm, list<dag> pattern> {
4258  let AddedComplexity = 1 in // try this before StoreUI
4259  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4260                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4261                               asm, pattern>,
4262          Sched<[WriteST]>;
4263
4264  def : InstAlias<asm # "\t$Rt, [$Rn]",
4265                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4266}
4267
4268multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4269                            list<dag> pat> {
4270  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4271  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4272                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4273                               asm, pat>,
4274          Sched<[WriteLD]>;
4275
4276  def : InstAlias<asm # "\t$Rt, [$Rn]",
4277                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4278}
4279
4280//---
4281// Load/store unscaled immediate, unprivileged
4282//---
4283
4284class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4285                                dag oops, dag iops, string asm>
4286    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4287  bits<5> Rt;
4288  bits<5> Rn;
4289  bits<9> offset;
4290  let Inst{31-30} = sz;
4291  let Inst{29-27} = 0b111;
4292  let Inst{26}    = V;
4293  let Inst{25-24} = 0b00;
4294  let Inst{23-22} = opc;
4295  let Inst{21}    = 0;
4296  let Inst{20-12} = offset;
4297  let Inst{11-10} = 0b10;
4298  let Inst{9-5}   = Rn;
4299  let Inst{4-0}   = Rt;
4300
4301  let DecoderMethod = "DecodeSignedLdStInstruction";
4302}
4303
4304multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4305                            RegisterClass regtype, string asm> {
4306  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4307  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4308                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4309          Sched<[WriteLD]>;
4310
4311  def : InstAlias<asm # "\t$Rt, [$Rn]",
4312                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4313}
4314
4315multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4316                             RegisterClass regtype, string asm> {
4317  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4318  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4319                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4320                                 asm>,
4321          Sched<[WriteST]>;
4322
4323  def : InstAlias<asm # "\t$Rt, [$Rn]",
4324                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4325}
4326
4327//---
4328// Load/store pre-indexed
4329//---
4330
4331class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4332                          string asm, string cstr, list<dag> pat>
4333    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4334  bits<5> Rt;
4335  bits<5> Rn;
4336  bits<9> offset;
4337  let Inst{31-30} = sz;
4338  let Inst{29-27} = 0b111;
4339  let Inst{26}    = V;
4340  let Inst{25-24} = 0;
4341  let Inst{23-22} = opc;
4342  let Inst{21}    = 0;
4343  let Inst{20-12} = offset;
4344  let Inst{11-10} = 0b11;
4345  let Inst{9-5}   = Rn;
4346  let Inst{4-0}   = Rt;
4347
4348  let DecoderMethod = "DecodeSignedLdStInstruction";
4349}
4350
4351let hasSideEffects = 0 in {
4352let mayStore = 0, mayLoad = 1 in
4353class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4354             string asm>
4355    : BaseLoadStorePreIdx<sz, V, opc,
4356                     (outs GPR64sp:$wback, regtype:$Rt),
4357                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4358                     "$Rn = $wback,@earlyclobber $wback", []>,
4359      Sched<[WriteAdr, WriteLD]>;
4360
4361let mayStore = 1, mayLoad = 0 in
4362class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4363                  string asm, SDPatternOperator storeop, ValueType Ty>
4364    : BaseLoadStorePreIdx<sz, V, opc,
4365                      (outs GPR64sp:$wback),
4366                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4367                      asm, "$Rn = $wback,@earlyclobber $wback",
4368      [(set GPR64sp:$wback,
4369            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4370      Sched<[WriteAdr, WriteST]>;
4371} // hasSideEffects = 0
4372
4373//---
4374// Load/store post-indexed
4375//---
4376
4377class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4378                          string asm, string cstr, list<dag> pat>
4379    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4380  bits<5> Rt;
4381  bits<5> Rn;
4382  bits<9> offset;
4383  let Inst{31-30} = sz;
4384  let Inst{29-27} = 0b111;
4385  let Inst{26}    = V;
4386  let Inst{25-24} = 0b00;
4387  let Inst{23-22} = opc;
4388  let Inst{21}    = 0b0;
4389  let Inst{20-12} = offset;
4390  let Inst{11-10} = 0b01;
4391  let Inst{9-5}   = Rn;
4392  let Inst{4-0}   = Rt;
4393
4394  let DecoderMethod = "DecodeSignedLdStInstruction";
4395}
4396
4397let hasSideEffects = 0 in {
4398let mayStore = 0, mayLoad = 1 in
4399class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4400             string asm>
4401    : BaseLoadStorePostIdx<sz, V, opc,
4402                      (outs GPR64sp:$wback, regtype:$Rt),
4403                      (ins GPR64sp:$Rn, simm9:$offset),
4404                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4405      Sched<[WriteAdr, WriteLD]>;
4406
4407let mayStore = 1, mayLoad = 0 in
4408class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4409                   string asm, SDPatternOperator storeop, ValueType Ty>
4410    : BaseLoadStorePostIdx<sz, V, opc,
4411                      (outs GPR64sp:$wback),
4412                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4413                       asm, "$Rn = $wback,@earlyclobber $wback",
4414      [(set GPR64sp:$wback,
4415            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4416    Sched<[WriteAdr, WriteST]>;
4417} // hasSideEffects = 0
4418
4419
4420//---
4421// Load/store pair
4422//---
4423
4424// (indexed, offset)
4425
4426class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4427                              string asm>
4428    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4429  bits<5> Rt;
4430  bits<5> Rt2;
4431  bits<5> Rn;
4432  bits<7> offset;
4433  let Inst{31-30} = opc;
4434  let Inst{29-27} = 0b101;
4435  let Inst{26}    = V;
4436  let Inst{25-23} = 0b010;
4437  let Inst{22}    = L;
4438  let Inst{21-15} = offset;
4439  let Inst{14-10} = Rt2;
4440  let Inst{9-5}   = Rn;
4441  let Inst{4-0}   = Rt;
4442
4443  let DecoderMethod = "DecodePairLdStInstruction";
4444}
4445
4446multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4447                          Operand indextype, string asm> {
4448  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4449  def i : BaseLoadStorePairOffset<opc, V, 1,
4450                                  (outs regtype:$Rt, regtype:$Rt2),
4451                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4452          Sched<[WriteLD, WriteLDHi]>;
4453
4454  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4455                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4456                                                  GPR64sp:$Rn, 0)>;
4457}
4458
4459
4460multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4461                           Operand indextype, string asm> {
4462  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4463  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4464                                  (ins regtype:$Rt, regtype:$Rt2,
4465                                       GPR64sp:$Rn, indextype:$offset),
4466                                  asm>,
4467          Sched<[WriteSTP]>;
4468
4469  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4470                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4471                                                  GPR64sp:$Rn, 0)>;
4472}
4473
4474// (pre-indexed)
4475class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4476                              string asm>
4477    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4478  bits<5> Rt;
4479  bits<5> Rt2;
4480  bits<5> Rn;
4481  bits<7> offset;
4482  let Inst{31-30} = opc;
4483  let Inst{29-27} = 0b101;
4484  let Inst{26}    = V;
4485  let Inst{25-23} = 0b011;
4486  let Inst{22}    = L;
4487  let Inst{21-15} = offset;
4488  let Inst{14-10} = Rt2;
4489  let Inst{9-5}   = Rn;
4490  let Inst{4-0}   = Rt;
4491
4492  let DecoderMethod = "DecodePairLdStInstruction";
4493}
4494
4495let hasSideEffects = 0 in {
4496let mayStore = 0, mayLoad = 1 in
4497class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4498                     Operand indextype, string asm>
4499    : BaseLoadStorePairPreIdx<opc, V, 1,
4500                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4501                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4502      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4503
4504let mayStore = 1, mayLoad = 0 in
4505class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4506                      Operand indextype, string asm>
4507    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4508                             (ins regtype:$Rt, regtype:$Rt2,
4509                                  GPR64sp:$Rn, indextype:$offset),
4510                             asm>,
4511      Sched<[WriteAdr, WriteSTP]>;
4512} // hasSideEffects = 0
4513
4514// (post-indexed)
4515
4516class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4517                              string asm>
4518    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4519  bits<5> Rt;
4520  bits<5> Rt2;
4521  bits<5> Rn;
4522  bits<7> offset;
4523  let Inst{31-30} = opc;
4524  let Inst{29-27} = 0b101;
4525  let Inst{26}    = V;
4526  let Inst{25-23} = 0b001;
4527  let Inst{22}    = L;
4528  let Inst{21-15} = offset;
4529  let Inst{14-10} = Rt2;
4530  let Inst{9-5}   = Rn;
4531  let Inst{4-0}   = Rt;
4532
4533  let DecoderMethod = "DecodePairLdStInstruction";
4534}
4535
4536let hasSideEffects = 0 in {
4537let mayStore = 0, mayLoad = 1 in
4538class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4539                      Operand idxtype, string asm>
4540    : BaseLoadStorePairPostIdx<opc, V, 1,
4541                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4542                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4543      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4544
4545let mayStore = 1, mayLoad = 0 in
4546class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4547                       Operand idxtype, string asm>
4548    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4549                             (ins regtype:$Rt, regtype:$Rt2,
4550                                  GPR64sp:$Rn, idxtype:$offset),
4551                             asm>,
4552      Sched<[WriteAdr, WriteSTP]>;
4553} // hasSideEffects = 0
4554
4555//  (no-allocate)
4556
4557class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4558                              string asm>
4559    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4560  bits<5> Rt;
4561  bits<5> Rt2;
4562  bits<5> Rn;
4563  bits<7> offset;
4564  let Inst{31-30} = opc;
4565  let Inst{29-27} = 0b101;
4566  let Inst{26}    = V;
4567  let Inst{25-23} = 0b000;
4568  let Inst{22}    = L;
4569  let Inst{21-15} = offset;
4570  let Inst{14-10} = Rt2;
4571  let Inst{9-5}   = Rn;
4572  let Inst{4-0}   = Rt;
4573
4574  let DecoderMethod = "DecodePairLdStInstruction";
4575}
4576
4577multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4578                           Operand indextype, string asm> {
4579  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4580  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4581                                   (outs regtype:$Rt, regtype:$Rt2),
4582                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4583          Sched<[WriteLD, WriteLDHi]>;
4584
4585
4586  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4587                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4588                                                  GPR64sp:$Rn, 0)>;
4589}
4590
4591multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4592                      Operand indextype, string asm> {
4593  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4594  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4595                                   (ins regtype:$Rt, regtype:$Rt2,
4596                                        GPR64sp:$Rn, indextype:$offset),
4597                                   asm>,
4598          Sched<[WriteSTP]>;
4599
4600  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4601                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4602                                                  GPR64sp:$Rn, 0)>;
4603}
4604
4605//---
4606// Load/store exclusive
4607//---
4608
4609// True exclusive operations write to and/or read from the system's exclusive
4610// monitors, which as far as a compiler is concerned can be modelled as a
4611// random shared memory address. Hence LoadExclusive mayStore.
4612//
4613// Since these instructions have the undefined register bits set to 1 in
4614// their canonical form, we need a post encoder method to set those bits
4615// to 1 when encoding these instructions. We do this using the
4616// fixLoadStoreExclusive function. This function has template parameters:
4617//
4618// fixLoadStoreExclusive<int hasRs, int hasRt2>
4619//
4620// hasRs indicates that the instruction uses the Rs field, so we won't set
4621// it to 1 (and the same for Rt2). We don't need template parameters for
4622// the other register fields since Rt and Rn are always used.
4623//
4624let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4625class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4626                             dag oops, dag iops, string asm, string operands>
4627    : I<oops, iops, asm, operands, "", []> {
4628  let Inst{31-30} = sz;
4629  let Inst{29-24} = 0b001000;
4630  let Inst{23}    = o2;
4631  let Inst{22}    = L;
4632  let Inst{21}    = o1;
4633  let Inst{15}    = o0;
4634
4635  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4636}
4637
4638// Neither Rs nor Rt2 operands.
4639class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4640                               dag oops, dag iops, string asm, string operands>
4641    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4642  bits<5> Rt;
4643  bits<5> Rn;
4644  let Inst{20-16} = 0b11111;
4645  let Unpredictable{20-16} = 0b11111;
4646  let Inst{14-10} = 0b11111;
4647  let Unpredictable{14-10} = 0b11111;
4648  let Inst{9-5} = Rn;
4649  let Inst{4-0} = Rt;
4650
4651  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4652}
4653
4654// Simple load acquires don't set the exclusive monitor
4655let mayLoad = 1, mayStore = 0 in
4656class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4657                  RegisterClass regtype, string asm>
4658    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4659                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4660      Sched<[WriteLD]>;
4661
4662class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4663                    RegisterClass regtype, string asm>
4664    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4665                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4666      Sched<[WriteLD]>;
4667
4668class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4669                       RegisterClass regtype, string asm>
4670    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4671                             (outs regtype:$Rt, regtype:$Rt2),
4672                             (ins GPR64sp0:$Rn), asm,
4673                             "\t$Rt, $Rt2, [$Rn]">,
4674      Sched<[WriteLD, WriteLDHi]> {
4675  bits<5> Rt;
4676  bits<5> Rt2;
4677  bits<5> Rn;
4678  let Inst{14-10} = Rt2;
4679  let Inst{9-5} = Rn;
4680  let Inst{4-0} = Rt;
4681
4682  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4683}
4684
4685// Simple store release operations do not check the exclusive monitor.
4686let mayLoad = 0, mayStore = 1 in
4687class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4688                   RegisterClass regtype, string asm>
4689    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4690                               (ins regtype:$Rt, GPR64sp:$Rn),
4691                               asm, "\t$Rt, [$Rn]">,
4692      Sched<[WriteST]>;
4693
4694let mayLoad = 1, mayStore = 1 in
4695class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4696                     RegisterClass regtype, string asm>
4697    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4698                             (ins regtype:$Rt, GPR64sp0:$Rn),
4699                             asm, "\t$Ws, $Rt, [$Rn]">,
4700      Sched<[WriteSTX]> {
4701  bits<5> Ws;
4702  bits<5> Rt;
4703  bits<5> Rn;
4704  let Inst{20-16} = Ws;
4705  let Inst{9-5} = Rn;
4706  let Inst{4-0} = Rt;
4707
4708  let Constraints = "@earlyclobber $Ws";
4709  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4710}
4711
4712class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4713                         RegisterClass regtype, string asm>
4714    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4715                             (outs GPR32:$Ws),
4716                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4717                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4718      Sched<[WriteSTX]> {
4719  bits<5> Ws;
4720  bits<5> Rt;
4721  bits<5> Rt2;
4722  bits<5> Rn;
4723  let Inst{20-16} = Ws;
4724  let Inst{14-10} = Rt2;
4725  let Inst{9-5} = Rn;
4726  let Inst{4-0} = Rt;
4727
4728  let Constraints = "@earlyclobber $Ws";
4729}
4730
4731// Armv8.5-A Memory Tagging Extension
4732class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4733                 string asm_opnds, string cstr, dag oops, dag iops>
4734    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4735      Sched<[]> {
4736  bits<5> Rn;
4737
4738  let Inst{31-24} = 0b11011001;
4739  let Inst{23-22} = opc1;
4740  let Inst{21}    = 1;
4741  // Inst{20-12} defined by subclass
4742  let Inst{11-10} = opc2;
4743  let Inst{9-5}   = Rn;
4744  // Inst{4-0} defined by subclass
4745}
4746
4747class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4748                   dag oops, dag iops>
4749    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4750                  "", oops, iops> {
4751  bits<5> Rt;
4752
4753  let Inst{20-12} = 0b000000000;
4754  let Inst{4-0}   = Rt;
4755
4756  let mayLoad = Load;
4757}
4758
4759class MemTagLoad<string asm_insn, string asm_opnds>
4760    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4761                 (outs GPR64:$wback),
4762                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4763  bits<5> Rt;
4764  bits<9> offset;
4765
4766  let Inst{20-12} = offset;
4767  let Inst{4-0}   = Rt;
4768
4769  let mayLoad = 1;
4770}
4771
4772class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4773                     string asm_opnds, string cstr, dag oops, dag iops>
4774    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4775  bits<5> Rt;
4776  bits<9> offset;
4777
4778  let Inst{20-12} = offset;
4779  let Inst{4-0}   = Rt;
4780
4781  let mayStore = 1;
4782}
4783
4784multiclass MemTagStore<bits<2> opc1, string insn> {
4785  def i :
4786    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4787                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4788  def PreIndex :
4789    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4790                    "$Rn = $wback",
4791                    (outs GPR64sp:$wback),
4792                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4793  def PostIndex :
4794    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4795                    "$Rn = $wback",
4796                    (outs GPR64sp:$wback),
4797                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4798
4799  def : InstAlias<insn # "\t$Rt, [$Rn]",
4800                  (!cast<Instruction>(NAME # "i") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4801}
4802
4803//---
4804// Exception generation
4805//---
4806
4807let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4808class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4809                          list<dag> pattern = []>
4810    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4811      Sched<[WriteSys]> {
4812  bits<16> imm;
4813  let Inst{31-24} = 0b11010100;
4814  let Inst{23-21} = op1;
4815  let Inst{20-5}  = imm;
4816  let Inst{4-2}   = 0b000;
4817  let Inst{1-0}   = ll;
4818}
4819
4820//---
4821// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4822//--
4823let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4824class UDFType<bits<16> opc, string asm>
4825  : I<(outs), (ins uimm16:$imm),
4826       asm, "\t$imm", "", []>,
4827    Sched<[]> {
4828  bits<16> imm;
4829  let Inst{31-16} = opc;
4830  let Inst{15-0} = imm;
4831}
4832}
4833let Predicates = [HasFPARMv8] in {
4834
4835//---
4836// Floating point to integer conversion
4837//---
4838
4839let mayRaiseFPException = 1, Uses = [FPCR] in
4840class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4841                      RegisterClass srcType, RegisterClass dstType,
4842                      string asm, list<dag> pattern>
4843    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4844         asm, "\t$Rd, $Rn", "", pattern>,
4845      Sched<[WriteFCvt]> {
4846  bits<5> Rd;
4847  bits<5> Rn;
4848  let Inst{30-29} = 0b00;
4849  let Inst{28-24} = 0b11110;
4850  let Inst{23-22} = type;
4851  let Inst{21}    = 1;
4852  let Inst{20-19} = rmode;
4853  let Inst{18-16} = opcode;
4854  let Inst{15-10} = 0;
4855  let Inst{9-5}   = Rn;
4856  let Inst{4-0}   = Rd;
4857}
4858
4859let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4860class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4861                      RegisterClass srcType, RegisterClass dstType,
4862                      Operand immType, string asm, list<dag> pattern>
4863    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4864         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4865      Sched<[WriteFCvt]> {
4866  bits<5> Rd;
4867  bits<5> Rn;
4868  bits<6> scale;
4869  let Inst{30-29} = 0b00;
4870  let Inst{28-24} = 0b11110;
4871  let Inst{23-22} = type;
4872  let Inst{21}    = 0;
4873  let Inst{20-19} = rmode;
4874  let Inst{18-16} = opcode;
4875  let Inst{15-10} = scale;
4876  let Inst{9-5}   = Rn;
4877  let Inst{4-0}   = Rd;
4878}
4879
4880multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4881           SDPatternOperator OpN> {
4882  // Unscaled half-precision to 32-bit
4883  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4884                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4885    let Inst{31} = 0; // 32-bit GPR flag
4886    let Predicates = [HasFullFP16];
4887  }
4888
4889  // Unscaled half-precision to 64-bit
4890  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4891                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4892    let Inst{31} = 1; // 64-bit GPR flag
4893    let Predicates = [HasFullFP16];
4894  }
4895
4896  // Unscaled single-precision to 32-bit
4897  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4898                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4899    let Inst{31} = 0; // 32-bit GPR flag
4900  }
4901
4902  // Unscaled single-precision to 64-bit
4903  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4904                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4905    let Inst{31} = 1; // 64-bit GPR flag
4906  }
4907
4908  // Unscaled double-precision to 32-bit
4909  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4910                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4911    let Inst{31} = 0; // 32-bit GPR flag
4912  }
4913
4914  // Unscaled double-precision to 64-bit
4915  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4916                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4917    let Inst{31} = 1; // 64-bit GPR flag
4918  }
4919}
4920
4921multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4922                             SDPatternOperator OpN> {
4923  // Scaled half-precision to 32-bit
4924  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4925                              fixedpoint_f16_i32, asm,
4926              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4927                                          fixedpoint_f16_i32:$scale)))]> {
4928    let Inst{31} = 0; // 32-bit GPR flag
4929    let scale{5} = 1;
4930    let Predicates = [HasFullFP16];
4931  }
4932
4933  // Scaled half-precision to 64-bit
4934  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4935                              fixedpoint_f16_i64, asm,
4936              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4937                                          fixedpoint_f16_i64:$scale)))]> {
4938    let Inst{31} = 1; // 64-bit GPR flag
4939    let Predicates = [HasFullFP16];
4940  }
4941
4942  // Scaled single-precision to 32-bit
4943  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4944                              fixedpoint_f32_i32, asm,
4945              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4946                                          fixedpoint_f32_i32:$scale)))]> {
4947    let Inst{31} = 0; // 32-bit GPR flag
4948    let scale{5} = 1;
4949  }
4950
4951  // Scaled single-precision to 64-bit
4952  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4953                              fixedpoint_f32_i64, asm,
4954              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4955                                          fixedpoint_f32_i64:$scale)))]> {
4956    let Inst{31} = 1; // 64-bit GPR flag
4957  }
4958
4959  // Scaled double-precision to 32-bit
4960  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4961                              fixedpoint_f64_i32, asm,
4962              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4963                                          fixedpoint_f64_i32:$scale)))]> {
4964    let Inst{31} = 0; // 32-bit GPR flag
4965    let scale{5} = 1;
4966  }
4967
4968  // Scaled double-precision to 64-bit
4969  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4970                              fixedpoint_f64_i64, asm,
4971              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4972                                          fixedpoint_f64_i64:$scale)))]> {
4973    let Inst{31} = 1; // 64-bit GPR flag
4974  }
4975}
4976
4977//---
4978// Integer to floating point conversion
4979//---
4980
4981let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4982class BaseIntegerToFP<bit isUnsigned,
4983                      RegisterClass srcType, RegisterClass dstType,
4984                      Operand immType, string asm, list<dag> pattern>
4985    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4986         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4987      Sched<[WriteFCvt]> {
4988  bits<5> Rd;
4989  bits<5> Rn;
4990  bits<6> scale;
4991  let Inst{30-24} = 0b0011110;
4992  let Inst{21-17} = 0b00001;
4993  let Inst{16}    = isUnsigned;
4994  let Inst{15-10} = scale;
4995  let Inst{9-5}   = Rn;
4996  let Inst{4-0}   = Rd;
4997}
4998
4999let mayRaiseFPException = 1, Uses = [FPCR] in
5000class BaseIntegerToFPUnscaled<bit isUnsigned,
5001                      RegisterClass srcType, RegisterClass dstType,
5002                      ValueType dvt, string asm, SDPatternOperator node>
5003    : I<(outs dstType:$Rd), (ins srcType:$Rn),
5004         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
5005      Sched<[WriteFCvt]> {
5006  bits<5> Rd;
5007  bits<5> Rn;
5008  bits<6> scale;
5009  let Inst{30-24} = 0b0011110;
5010  let Inst{21-17} = 0b10001;
5011  let Inst{16}    = isUnsigned;
5012  let Inst{15-10} = 0b000000;
5013  let Inst{9-5}   = Rn;
5014  let Inst{4-0}   = Rd;
5015}
5016
5017multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
5018  // Unscaled
5019  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
5020    let Inst{31} = 0; // 32-bit GPR flag
5021    let Inst{23-22} = 0b11; // 16-bit FPR flag
5022    let Predicates = [HasFullFP16];
5023  }
5024
5025  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
5026    let Inst{31} = 0; // 32-bit GPR flag
5027    let Inst{23-22} = 0b00; // 32-bit FPR flag
5028  }
5029
5030  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
5031    let Inst{31} = 0; // 32-bit GPR flag
5032    let Inst{23-22} = 0b01; // 64-bit FPR flag
5033  }
5034
5035  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
5036    let Inst{31} = 1; // 64-bit GPR flag
5037    let Inst{23-22} = 0b11; // 16-bit FPR flag
5038    let Predicates = [HasFullFP16];
5039  }
5040
5041  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
5042    let Inst{31} = 1; // 64-bit GPR flag
5043    let Inst{23-22} = 0b00; // 32-bit FPR flag
5044  }
5045
5046  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
5047    let Inst{31} = 1; // 64-bit GPR flag
5048    let Inst{23-22} = 0b01; // 64-bit FPR flag
5049  }
5050
5051  // Scaled
5052  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_recip_f16_i32, asm,
5053                             [(set (f16 FPR16:$Rd),
5054                                   (fmul (node GPR32:$Rn),
5055                                         fixedpoint_recip_f16_i32:$scale))]> {
5056    let Inst{31} = 0; // 32-bit GPR flag
5057    let Inst{23-22} = 0b11; // 16-bit FPR flag
5058    let scale{5} = 1;
5059    let Predicates = [HasFullFP16];
5060  }
5061
5062  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_recip_f32_i32, asm,
5063                             [(set FPR32:$Rd,
5064                                   (fmul (node GPR32:$Rn),
5065                                         fixedpoint_recip_f32_i32:$scale))]> {
5066    let Inst{31} = 0; // 32-bit GPR flag
5067    let Inst{23-22} = 0b00; // 32-bit FPR flag
5068    let scale{5} = 1;
5069  }
5070
5071  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_recip_f64_i32, asm,
5072                             [(set FPR64:$Rd,
5073                                   (fmul (node GPR32:$Rn),
5074                                         fixedpoint_recip_f64_i32:$scale))]> {
5075    let Inst{31} = 0; // 32-bit GPR flag
5076    let Inst{23-22} = 0b01; // 64-bit FPR flag
5077    let scale{5} = 1;
5078  }
5079
5080  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_recip_f16_i64, asm,
5081                             [(set (f16 FPR16:$Rd),
5082                                   (fmul (node GPR64:$Rn),
5083                                         fixedpoint_recip_f16_i64:$scale))]> {
5084    let Inst{31} = 1; // 64-bit GPR flag
5085    let Inst{23-22} = 0b11; // 16-bit FPR flag
5086    let Predicates = [HasFullFP16];
5087  }
5088
5089  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_recip_f32_i64, asm,
5090                             [(set FPR32:$Rd,
5091                                   (fmul (node GPR64:$Rn),
5092                                         fixedpoint_recip_f32_i64:$scale))]> {
5093    let Inst{31} = 1; // 64-bit GPR flag
5094    let Inst{23-22} = 0b00; // 32-bit FPR flag
5095  }
5096
5097  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_recip_f64_i64, asm,
5098                             [(set FPR64:$Rd,
5099                                   (fmul (node GPR64:$Rn),
5100                                         fixedpoint_recip_f64_i64:$scale))]> {
5101    let Inst{31} = 1; // 64-bit GPR flag
5102    let Inst{23-22} = 0b01; // 64-bit FPR flag
5103  }
5104}
5105
5106//---
5107// Unscaled integer <-> floating point conversion (i.e. FMOV)
5108//---
5109
5110let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5111class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
5112                      RegisterClass srcType, RegisterClass dstType,
5113                      string asm>
5114    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
5115        // We use COPY_TO_REGCLASS for these bitconvert operations.
5116        // copyPhysReg() expands the resultant COPY instructions after
5117        // regalloc is done. This gives greater freedom for the allocator
5118        // and related passes (coalescing, copy propagation, et. al.) to
5119        // be more effective.
5120        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
5121      Sched<[WriteFCopy]> {
5122  bits<5> Rd;
5123  bits<5> Rn;
5124  let Inst{30-24} = 0b0011110;
5125  let Inst{21}    = 1;
5126  let Inst{20-19} = rmode;
5127  let Inst{18-16} = opcode;
5128  let Inst{15-10} = 0b000000;
5129  let Inst{9-5}   = Rn;
5130  let Inst{4-0}   = Rd;
5131}
5132
5133let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5134class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
5135                     RegisterClass srcType, RegisterOperand dstType, string asm,
5136                     string kind>
5137    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5138        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
5139      Sched<[WriteFCopy]> {
5140  bits<5> Rd;
5141  bits<5> Rn;
5142  let Inst{30-23} = 0b00111101;
5143  let Inst{21}    = 1;
5144  let Inst{20-19} = rmode;
5145  let Inst{18-16} = opcode;
5146  let Inst{15-10} = 0b000000;
5147  let Inst{9-5}   = Rn;
5148  let Inst{4-0}   = Rd;
5149
5150  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5151}
5152
5153let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5154class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
5155                     RegisterOperand srcType, RegisterClass dstType, string asm,
5156                     string kind>
5157    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5158        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
5159      Sched<[WriteFCopy]> {
5160  bits<5> Rd;
5161  bits<5> Rn;
5162  let Inst{30-23} = 0b00111101;
5163  let Inst{21}    = 1;
5164  let Inst{20-19} = rmode;
5165  let Inst{18-16} = opcode;
5166  let Inst{15-10} = 0b000000;
5167  let Inst{9-5}   = Rn;
5168  let Inst{4-0}   = Rd;
5169
5170  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5171}
5172
5173
5174multiclass UnscaledConversion<string asm> {
5175  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
5176    let Inst{31} = 0; // 32-bit GPR flag
5177    let Inst{23-22} = 0b11; // 16-bit FPR flag
5178    let Predicates = [HasFullFP16];
5179  }
5180
5181  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
5182    let Inst{31} = 1; // 64-bit GPR flag
5183    let Inst{23-22} = 0b11; // 16-bit FPR flag
5184    let Predicates = [HasFullFP16];
5185  }
5186
5187  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
5188    let Inst{31} = 0; // 32-bit GPR flag
5189    let Inst{23-22} = 0b00; // 32-bit FPR flag
5190  }
5191
5192  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
5193    let Inst{31} = 1; // 64-bit GPR flag
5194    let Inst{23-22} = 0b01; // 64-bit FPR flag
5195  }
5196
5197  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
5198    let Inst{31} = 0; // 32-bit GPR flag
5199    let Inst{23-22} = 0b11; // 16-bit FPR flag
5200    let Predicates = [HasFullFP16];
5201  }
5202
5203  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
5204    let Inst{31} = 1; // 64-bit GPR flag
5205    let Inst{23-22} = 0b11; // 16-bit FPR flag
5206    let Predicates = [HasFullFP16];
5207  }
5208
5209  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
5210    let Inst{31} = 0; // 32-bit GPR flag
5211    let Inst{23-22} = 0b00; // 32-bit FPR flag
5212  }
5213
5214  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
5215    let Inst{31} = 1; // 64-bit GPR flag
5216    let Inst{23-22} = 0b01; // 64-bit FPR flag
5217  }
5218
5219  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
5220                                             asm, ".d"> {
5221    let Inst{31} = 1;
5222    let Inst{22} = 0;
5223  }
5224
5225  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
5226                                               asm, ".d"> {
5227    let Inst{31} = 1;
5228    let Inst{22} = 0;
5229  }
5230}
5231
5232//---
5233// Floating point conversion
5234//---
5235
5236let mayRaiseFPException = 1, Uses = [FPCR] in
5237class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
5238                       RegisterClass srcType, string asm, list<dag> pattern>
5239    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
5240      Sched<[WriteFCvt]> {
5241  bits<5> Rd;
5242  bits<5> Rn;
5243  let Inst{31-24} = 0b00011110;
5244  let Inst{23-22} = type;
5245  let Inst{21-17} = 0b10001;
5246  let Inst{16-15} = opcode;
5247  let Inst{14-10} = 0b10000;
5248  let Inst{9-5}   = Rn;
5249  let Inst{4-0}   = Rd;
5250}
5251
5252multiclass FPConversion<string asm> {
5253  // Double-precision to Half-precision
5254  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
5255                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
5256
5257  // Double-precision to Single-precision
5258  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
5259                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5260
5261  // Half-precision to Double-precision
5262  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5263                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5264
5265  // Half-precision to Single-precision
5266  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5267                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5268
5269  // Single-precision to Double-precision
5270  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5271                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5272
5273  // Single-precision to Half-precision
5274  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5275                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5276}
5277
5278//---
5279// Single operand floating point data processing
5280//---
5281
5282let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5283class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5284                              ValueType vt, string asm, SDPatternOperator node>
5285    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5286         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5287      Sched<[WriteF]> {
5288  bits<5> Rd;
5289  bits<5> Rn;
5290  let Inst{31-24} = 0b00011110;
5291  let Inst{21}    = 0b1;
5292  let Inst{20-15} = opcode;
5293  let Inst{14-10} = 0b10000;
5294  let Inst{9-5}   = Rn;
5295  let Inst{4-0}   = Rd;
5296}
5297
5298multiclass SingleOperandFPData<bits<4> opcode, string asm,
5299                               SDPatternOperator node = null_frag,
5300                               int fpexceptions = 1> {
5301  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
5302  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5303    let Inst{23-22} = 0b11; // 16-bit size flag
5304    let Predicates = [HasFullFP16];
5305  }
5306
5307  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5308    let Inst{23-22} = 0b00; // 32-bit size flag
5309  }
5310
5311  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5312    let Inst{23-22} = 0b01; // 64-bit size flag
5313  }
5314  }
5315}
5316
5317multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5318                                       SDPatternOperator node = null_frag>
5319    : SingleOperandFPData<opcode, asm, node, 0>;
5320
5321let mayRaiseFPException = 1, Uses = [FPCR] in
5322multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5323                  SDPatternOperator node = null_frag>{
5324
5325  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5326    let Inst{23-22} = 0b00; // 32-bit registers
5327  }
5328
5329  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5330    let Inst{23-22} = 0b01; // 64-bit registers
5331  }
5332}
5333
5334// FRInt[32|64][Z|N] instructions
5335multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5336      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5337
5338//---
5339// Two operand floating point data processing
5340//---
5341
5342let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5343class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5344                           string asm, list<dag> pat>
5345    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5346         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5347      Sched<[WriteF]> {
5348  bits<5> Rd;
5349  bits<5> Rn;
5350  bits<5> Rm;
5351  let Inst{31-24} = 0b00011110;
5352  let Inst{21}    = 1;
5353  let Inst{20-16} = Rm;
5354  let Inst{15-12} = opcode;
5355  let Inst{11-10} = 0b10;
5356  let Inst{9-5}   = Rn;
5357  let Inst{4-0}   = Rd;
5358}
5359
5360multiclass TwoOperandFPData<bits<4> opcode, string asm,
5361                            SDPatternOperator node = null_frag> {
5362  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5363                         [(set (f16 FPR16:$Rd),
5364                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5365    let Inst{23-22} = 0b11; // 16-bit size flag
5366    let Predicates = [HasFullFP16];
5367  }
5368
5369  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5370                         [(set (f32 FPR32:$Rd),
5371                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5372    let Inst{23-22} = 0b00; // 32-bit size flag
5373  }
5374
5375  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5376                         [(set (f64 FPR64:$Rd),
5377                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5378    let Inst{23-22} = 0b01; // 64-bit size flag
5379  }
5380}
5381
5382multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5383                               SDPatternOperator node> {
5384  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5385                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5386    let Inst{23-22} = 0b11; // 16-bit size flag
5387    let Predicates = [HasFullFP16];
5388  }
5389
5390  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5391                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5392    let Inst{23-22} = 0b00; // 32-bit size flag
5393  }
5394
5395  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5396                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5397    let Inst{23-22} = 0b01; // 64-bit size flag
5398  }
5399}
5400
5401
5402//---
5403// Three operand floating point data processing
5404//---
5405
5406let mayRaiseFPException = 1, Uses = [FPCR] in
5407class BaseThreeOperandFPData<bit isNegated, bit isSub,
5408                             RegisterClass regtype, string asm, list<dag> pat>
5409    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5410         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5411      Sched<[WriteFMul]> {
5412  bits<5> Rd;
5413  bits<5> Rn;
5414  bits<5> Rm;
5415  bits<5> Ra;
5416  let Inst{31-24} = 0b00011111;
5417  let Inst{21}    = isNegated;
5418  let Inst{20-16} = Rm;
5419  let Inst{15}    = isSub;
5420  let Inst{14-10} = Ra;
5421  let Inst{9-5}   = Rn;
5422  let Inst{4-0}   = Rd;
5423}
5424
5425multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5426                              SDPatternOperator node> {
5427  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5428            [(set (f16 FPR16:$Rd),
5429                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5430    let Inst{23-22} = 0b11; // 16-bit size flag
5431    let Predicates = [HasFullFP16];
5432  }
5433
5434  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5435            [(set FPR32:$Rd,
5436                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5437    let Inst{23-22} = 0b00; // 32-bit size flag
5438  }
5439
5440  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5441            [(set FPR64:$Rd,
5442                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5443    let Inst{23-22} = 0b01; // 64-bit size flag
5444  }
5445
5446  let Predicates = [HasFullFP16] in {
5447  def : Pat<(f16 (node (f16 FPR16:$Rn),
5448                       (f16 (extractelt (v8f16 V128:$Rm), (i64 0))),
5449                       (f16 FPR16:$Ra))),
5450            (!cast<Instruction>(NAME # Hrrr)
5451              FPR16:$Rn, (f16 (EXTRACT_SUBREG V128:$Rm, hsub)), FPR16:$Ra)>;
5452
5453  def : Pat<(f16 (node (f16 (extractelt (v8f16 V128:$Rn), (i64 0))),
5454                       (f16 FPR16:$Rm),
5455                       (f16 FPR16:$Ra))),
5456            (!cast<Instruction>(NAME # Hrrr)
5457              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), FPR16:$Rm, FPR16:$Ra)>;
5458  }
5459
5460  def : Pat<(f32 (node (f32 FPR32:$Rn),
5461                       (f32 (extractelt (v4f32 V128:$Rm), (i64 0))),
5462                       (f32 FPR32:$Ra))),
5463            (!cast<Instruction>(NAME # Srrr)
5464              FPR32:$Rn, (EXTRACT_SUBREG V128:$Rm, ssub), FPR32:$Ra)>;
5465
5466  def : Pat<(f32 (node (f32 (extractelt (v4f32 V128:$Rn), (i64 0))),
5467                       (f32 FPR32:$Rm),
5468                       (f32 FPR32:$Ra))),
5469            (!cast<Instruction>(NAME # Srrr)
5470              (EXTRACT_SUBREG V128:$Rn, ssub), FPR32:$Rm, FPR32:$Ra)>;
5471
5472  def : Pat<(f64 (node (f64 FPR64:$Rn),
5473                       (f64 (extractelt (v2f64 V128:$Rm), (i64 0))),
5474                       (f64 FPR64:$Ra))),
5475            (!cast<Instruction>(NAME # Drrr)
5476              FPR64:$Rn, (EXTRACT_SUBREG V128:$Rm, dsub), FPR64:$Ra)>;
5477
5478  def : Pat<(f64 (node (f64 (extractelt (v2f64 V128:$Rn), (i64 0))),
5479                       (f64 FPR64:$Rm),
5480                       (f64 FPR64:$Ra))),
5481            (!cast<Instruction>(NAME # Drrr)
5482              (EXTRACT_SUBREG V128:$Rn, dsub), FPR64:$Rm, FPR64:$Ra)>;
5483}
5484
5485//---
5486// Floating point data comparisons
5487//---
5488
5489let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5490class BaseOneOperandFPComparison<bit signalAllNans,
5491                                 RegisterClass regtype, string asm,
5492                                 list<dag> pat>
5493    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5494      Sched<[WriteFCmp]> {
5495  bits<5> Rn;
5496  let Inst{31-24} = 0b00011110;
5497  let Inst{21}    = 1;
5498
5499  let Inst{15-10} = 0b001000;
5500  let Inst{9-5}   = Rn;
5501  let Inst{4}     = signalAllNans;
5502  let Inst{3-0}   = 0b1000;
5503
5504  // Rm should be 0b00000 canonically, but we need to accept any value.
5505  let PostEncoderMethod = "fixOneOperandFPComparison";
5506}
5507
5508let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5509class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5510                                string asm, list<dag> pat>
5511    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5512      Sched<[WriteFCmp]> {
5513  bits<5> Rm;
5514  bits<5> Rn;
5515  let Inst{31-24} = 0b00011110;
5516  let Inst{21}    = 1;
5517  let Inst{20-16} = Rm;
5518  let Inst{15-10} = 0b001000;
5519  let Inst{9-5}   = Rn;
5520  let Inst{4}     = signalAllNans;
5521  let Inst{3-0}   = 0b0000;
5522}
5523
5524multiclass FPComparison<bit signalAllNans, string asm,
5525                        SDPatternOperator OpNode = null_frag> {
5526  let Defs = [NZCV] in {
5527  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5528      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5529    let Inst{23-22} = 0b11;
5530    let Predicates = [HasFullFP16];
5531  }
5532
5533  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5534      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5535    let Inst{23-22} = 0b11;
5536    let Predicates = [HasFullFP16];
5537  }
5538
5539  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5540      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5541    let Inst{23-22} = 0b00;
5542  }
5543
5544  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5545      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5546    let Inst{23-22} = 0b00;
5547  }
5548
5549  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5550      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5551    let Inst{23-22} = 0b01;
5552  }
5553
5554  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5555      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5556    let Inst{23-22} = 0b01;
5557  }
5558  } // Defs = [NZCV]
5559}
5560
5561//---
5562// Floating point conditional comparisons
5563//---
5564
5565let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5566class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5567                           string mnemonic, list<dag> pat>
5568    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5569         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5570      Sched<[WriteFCmp]> {
5571  let Uses = [NZCV];
5572  let Defs = [NZCV];
5573
5574  bits<5> Rn;
5575  bits<5> Rm;
5576  bits<4> nzcv;
5577  bits<4> cond;
5578
5579  let Inst{31-24} = 0b00011110;
5580  let Inst{21}    = 1;
5581  let Inst{20-16} = Rm;
5582  let Inst{15-12} = cond;
5583  let Inst{11-10} = 0b01;
5584  let Inst{9-5}   = Rn;
5585  let Inst{4}     = signalAllNans;
5586  let Inst{3-0}   = nzcv;
5587}
5588
5589multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5590                            SDPatternOperator OpNode = null_frag> {
5591  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5592      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5593                          (i32 imm:$cond), NZCV))]> {
5594    let Inst{23-22} = 0b11;
5595    let Predicates = [HasFullFP16];
5596  }
5597
5598  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5599      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5600                          (i32 imm:$cond), NZCV))]> {
5601    let Inst{23-22} = 0b00;
5602  }
5603
5604  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5605      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5606                          (i32 imm:$cond), NZCV))]> {
5607    let Inst{23-22} = 0b01;
5608  }
5609}
5610
5611//---
5612// Floating point conditional select
5613//---
5614
5615class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5616    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5617         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5618         [(set regtype:$Rd,
5619               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5620                          (i32 imm:$cond), NZCV))]>,
5621      Sched<[WriteF]> {
5622  bits<5> Rd;
5623  bits<5> Rn;
5624  bits<5> Rm;
5625  bits<4> cond;
5626
5627  let Inst{31-24} = 0b00011110;
5628  let Inst{21}    = 1;
5629  let Inst{20-16} = Rm;
5630  let Inst{15-12} = cond;
5631  let Inst{11-10} = 0b11;
5632  let Inst{9-5}   = Rn;
5633  let Inst{4-0}   = Rd;
5634}
5635
5636multiclass FPCondSelect<string asm> {
5637  let Uses = [NZCV] in {
5638  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5639    let Inst{23-22} = 0b11;
5640    let Predicates = [HasFullFP16];
5641  }
5642
5643  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5644    let Inst{23-22} = 0b00;
5645  }
5646
5647  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5648    let Inst{23-22} = 0b01;
5649  }
5650  } // Uses = [NZCV]
5651}
5652
5653//---
5654// Floating move immediate
5655//---
5656
5657class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5658  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5659      [(set regtype:$Rd, fpimmtype:$imm)]>,
5660    Sched<[WriteFImm]> {
5661  bits<5> Rd;
5662  bits<8> imm;
5663  let Inst{31-24} = 0b00011110;
5664  let Inst{21}    = 1;
5665  let Inst{20-13} = imm;
5666  let Inst{12-5}  = 0b10000000;
5667  let Inst{4-0}   = Rd;
5668}
5669
5670multiclass FPMoveImmediate<string asm> {
5671  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5672    let Inst{23-22} = 0b11;
5673    let Predicates = [HasFullFP16];
5674  }
5675
5676  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5677    let Inst{23-22} = 0b00;
5678  }
5679
5680  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5681    let Inst{23-22} = 0b01;
5682  }
5683}
5684} // end of 'let Predicates = [HasFPARMv8]'
5685
5686//----------------------------------------------------------------------------
5687// AdvSIMD
5688//----------------------------------------------------------------------------
5689
5690let Predicates = [HasNEON] in {
5691
5692//----------------------------------------------------------------------------
5693// AdvSIMD three register vector instructions
5694//----------------------------------------------------------------------------
5695
5696let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5697class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5698                        RegisterOperand regtype, string asm, string kind,
5699                        list<dag> pattern>
5700  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5701      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5702      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5703    Sched<[!if(Q, WriteVq, WriteVd)]> {
5704  bits<5> Rd;
5705  bits<5> Rn;
5706  bits<5> Rm;
5707  let Inst{31}    = 0;
5708  let Inst{30}    = Q;
5709  let Inst{29}    = U;
5710  let Inst{28-24} = 0b01110;
5711  let Inst{23-21} = size;
5712  let Inst{20-16} = Rm;
5713  let Inst{15-11} = opcode;
5714  let Inst{10}    = 1;
5715  let Inst{9-5}   = Rn;
5716  let Inst{4-0}   = Rd;
5717}
5718
5719let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5720class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5721                        RegisterOperand regtype, string asm, string kind,
5722                        list<dag> pattern>
5723  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5724      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5725      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5726    Sched<[!if(Q, WriteVq, WriteVd)]> {
5727  bits<5> Rd;
5728  bits<5> Rn;
5729  bits<5> Rm;
5730  let Inst{31}    = 0;
5731  let Inst{30}    = Q;
5732  let Inst{29}    = U;
5733  let Inst{28-24} = 0b01110;
5734  let Inst{23-21} = size;
5735  let Inst{20-16} = Rm;
5736  let Inst{15-11} = opcode;
5737  let Inst{10}    = 1;
5738  let Inst{9-5}   = Rn;
5739  let Inst{4-0}   = Rd;
5740}
5741
5742let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5743class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5744  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5745    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5746
5747multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5748  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5749             [(set (v8i8 V64:$dst),
5750                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5751  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5752             [(set (v16i8 V128:$dst),
5753                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5754                           (v16i8 V128:$Rm)))]>;
5755
5756  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5757                           (v4i16 V64:$RHS))),
5758          (!cast<Instruction>(NAME#"v8i8")
5759            V64:$LHS, V64:$MHS, V64:$RHS)>;
5760  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5761                           (v2i32 V64:$RHS))),
5762          (!cast<Instruction>(NAME#"v8i8")
5763            V64:$LHS, V64:$MHS, V64:$RHS)>;
5764  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5765                           (v1i64 V64:$RHS))),
5766          (!cast<Instruction>(NAME#"v8i8")
5767            V64:$LHS, V64:$MHS, V64:$RHS)>;
5768
5769  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5770                           (v8i16 V128:$RHS))),
5771      (!cast<Instruction>(NAME#"v16i8")
5772        V128:$LHS, V128:$MHS, V128:$RHS)>;
5773  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5774                           (v4i32 V128:$RHS))),
5775      (!cast<Instruction>(NAME#"v16i8")
5776        V128:$LHS, V128:$MHS, V128:$RHS)>;
5777  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5778                           (v2i64 V128:$RHS))),
5779      (!cast<Instruction>(NAME#"v16i8")
5780        V128:$LHS, V128:$MHS, V128:$RHS)>;
5781}
5782
5783// All operand sizes distinguished in the encoding.
5784multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5785                               SDPatternOperator OpNode> {
5786  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5787                                      asm, ".8b",
5788         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5789  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5790                                      asm, ".16b",
5791         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5792  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5793                                      asm, ".4h",
5794         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5795  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5796                                      asm, ".8h",
5797         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5798  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5799                                      asm, ".2s",
5800         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5801  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5802                                      asm, ".4s",
5803         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5804  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5805                                      asm, ".2d",
5806         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5807}
5808
5809multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5810  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5811          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5812  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5813          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5814  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5815          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5816
5817  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5818          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5819  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5820          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5821  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5822          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5823  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5824          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5825}
5826
5827// As above, but D sized elements unsupported.
5828multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5829                                  SDPatternOperator OpNode> {
5830  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5831                                      asm, ".8b",
5832        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5833  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5834                                      asm, ".16b",
5835        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5836  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5837                                      asm, ".4h",
5838        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5839  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5840                                      asm, ".8h",
5841        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5842  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5843                                      asm, ".2s",
5844        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5845  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5846                                      asm, ".4s",
5847        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5848}
5849
5850multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5851                                  SDPatternOperator OpNode> {
5852  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5853                                      asm, ".8b",
5854      [(set (v8i8 V64:$dst),
5855            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5856  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5857                                      asm, ".16b",
5858      [(set (v16i8 V128:$dst),
5859            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5860  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5861                                      asm, ".4h",
5862      [(set (v4i16 V64:$dst),
5863            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5864  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5865                                      asm, ".8h",
5866      [(set (v8i16 V128:$dst),
5867            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5868  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5869                                      asm, ".2s",
5870      [(set (v2i32 V64:$dst),
5871            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5872  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5873                                      asm, ".4s",
5874      [(set (v4i32 V128:$dst),
5875            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5876}
5877
5878// As above, but only B sized elements supported.
5879multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5880                                SDPatternOperator OpNode> {
5881  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5882                                      asm, ".8b",
5883    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5884  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5885                                      asm, ".16b",
5886    [(set (v16i8 V128:$Rd),
5887          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5888}
5889
5890// As above, but only floating point elements supported.
5891let mayRaiseFPException = 1, Uses = [FPCR] in
5892multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5893                                 string asm, SDPatternOperator OpNode> {
5894  let Predicates = [HasNEON, HasFullFP16] in {
5895  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5896                                      asm, ".4h",
5897        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5898  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5899                                      asm, ".8h",
5900        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5901  } // Predicates = [HasNEON, HasFullFP16]
5902  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5903                                      asm, ".2s",
5904        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5905  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5906                                      asm, ".4s",
5907        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5908  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5909                                      asm, ".2d",
5910        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5911}
5912
5913let mayRaiseFPException = 1, Uses = [FPCR] in
5914multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5915                                    string asm,
5916                                    SDPatternOperator OpNode> {
5917  let Predicates = [HasNEON, HasFullFP16] in {
5918  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5919                                      asm, ".4h",
5920        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5921  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5922                                      asm, ".8h",
5923        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5924  } // Predicates = [HasNEON, HasFullFP16]
5925  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5926                                      asm, ".2s",
5927        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5928  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5929                                      asm, ".4s",
5930        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5931  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5932                                      asm, ".2d",
5933        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5934}
5935
5936let mayRaiseFPException = 1, Uses = [FPCR] in
5937multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5938                                 string asm, SDPatternOperator OpNode> {
5939  let Predicates = [HasNEON, HasFullFP16] in {
5940  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5941                                      asm, ".4h",
5942     [(set (v4f16 V64:$dst),
5943           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5944  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5945                                      asm, ".8h",
5946     [(set (v8f16 V128:$dst),
5947           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5948  } // Predicates = [HasNEON, HasFullFP16]
5949  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5950                                      asm, ".2s",
5951     [(set (v2f32 V64:$dst),
5952           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5953  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5954                                      asm, ".4s",
5955     [(set (v4f32 V128:$dst),
5956           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5957  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5958                                      asm, ".2d",
5959     [(set (v2f64 V128:$dst),
5960           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5961}
5962
5963// As above, but D and B sized elements unsupported.
5964let mayRaiseFPException = 1, Uses = [FPCR] in
5965multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5966                                SDPatternOperator OpNode> {
5967  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5968                                      asm, ".4h",
5969        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5970  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5971                                      asm, ".8h",
5972        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5973  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5974                                      asm, ".2s",
5975        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5976  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5977                                      asm, ".4s",
5978        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5979}
5980
5981// Logical three vector ops share opcode bits, and only use B sized elements.
5982multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5983                                  SDPatternOperator OpNode = null_frag> {
5984  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5985                                     asm, ".8b",
5986                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5987  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5988                                     asm, ".16b",
5989                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5990
5991  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5992          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5993  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5994          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5995  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5996          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5997
5998  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5999      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6000  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
6001      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6002  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
6003      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6004}
6005
6006multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
6007                                  string asm, SDPatternOperator OpNode = null_frag> {
6008  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
6009                                     asm, ".8b",
6010             [(set (v8i8 V64:$dst),
6011                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6012  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
6013                                     asm, ".16b",
6014             [(set (v16i8 V128:$dst),
6015                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
6016                           (v16i8 V128:$Rm)))]>;
6017
6018  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
6019                           (v4i16 V64:$RHS))),
6020          (!cast<Instruction>(NAME#"v8i8")
6021            V64:$LHS, V64:$MHS, V64:$RHS)>;
6022  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
6023                           (v2i32 V64:$RHS))),
6024          (!cast<Instruction>(NAME#"v8i8")
6025            V64:$LHS, V64:$MHS, V64:$RHS)>;
6026  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
6027                           (v1i64 V64:$RHS))),
6028          (!cast<Instruction>(NAME#"v8i8")
6029            V64:$LHS, V64:$MHS, V64:$RHS)>;
6030
6031  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
6032                           (v8i16 V128:$RHS))),
6033      (!cast<Instruction>(NAME#"v16i8")
6034        V128:$LHS, V128:$MHS, V128:$RHS)>;
6035  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
6036                           (v4i32 V128:$RHS))),
6037      (!cast<Instruction>(NAME#"v16i8")
6038        V128:$LHS, V128:$MHS, V128:$RHS)>;
6039  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
6040                           (v2i64 V128:$RHS))),
6041      (!cast<Instruction>(NAME#"v16i8")
6042        V128:$LHS, V128:$MHS, V128:$RHS)>;
6043}
6044
6045// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
6046// bytes from S-sized elements.
6047class BaseSIMDThreeSameVectorDot<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
6048                                 string kind1, string kind2, RegisterOperand RegType,
6049                                 ValueType AccumType, ValueType InputType,
6050                                 SDPatternOperator OpNode> :
6051        BaseSIMDThreeSameVectorTied<Q, U, {sz, 0b0}, {0b1, opc}, RegType, asm, kind1,
6052        [(set (AccumType RegType:$dst),
6053              (OpNode (AccumType RegType:$Rd),
6054                      (InputType RegType:$Rn),
6055                      (InputType RegType:$Rm)))]> {
6056  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6057}
6058
6059multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
6060  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, 0b10, {0b001, Mixed}, asm, ".2s", ".8b", V64,
6061                                         v2i32, v8i8, OpNode>;
6062  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, 0b10, {0b001, Mixed}, asm, ".4s", ".16b", V128,
6063                                         v4i32, v16i8, OpNode>;
6064}
6065
6066// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
6067// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
6068// 8H to 4S, when Q=1).
6069let mayRaiseFPException = 1, Uses = [FPCR] in
6070class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
6071                                 string kind2, RegisterOperand RegType,
6072                                 ValueType AccumType, ValueType InputType,
6073                                 SDPatternOperator OpNode> :
6074        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
6075		[(set (AccumType RegType:$dst),
6076              (OpNode (AccumType RegType:$Rd),
6077                      (InputType RegType:$Rn),
6078                      (InputType RegType:$Rm)))]> {
6079  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6080  let Inst{13} = b13;
6081}
6082
6083multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
6084                                  SDPatternOperator OpNode> {
6085  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
6086                                         v2f32, v4f16, OpNode>;
6087  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
6088                                         v4f32, v8f16, OpNode>;
6089}
6090
6091multiclass SIMDThreeSameVectorMLA<bit Q, string asm>{
6092  def v8f16 : BaseSIMDThreeSameVectorDot<Q, 0b0, 0b11, 0b1111, asm, ".8h", ".16b",
6093                                         V128, v8f16, v16i8, null_frag>;
6094}
6095
6096multiclass SIMDThreeSameVectorMLAL<bit Q, bits<2> sz, string asm>{
6097  def v4f32 : BaseSIMDThreeSameVectorDot<Q, 0b0, sz, 0b1000, asm, ".4s", ".16b",
6098                                         V128, v4f32, v16i8, null_frag>;
6099}
6100
6101// FP8 assembly/disassembly classes
6102
6103//----------------------------------------------------------------------------
6104// FP8 Advanced SIMD three-register extension
6105//----------------------------------------------------------------------------
6106class BaseSIMDThreeVectors<bit Q, bit U, bits<2> size, bits<4> op,
6107                           RegisterOperand regtype1,
6108                           RegisterOperand regtype2, string asm,
6109                           string kind1, string kind2>
6110  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, regtype2:$Rm), asm,
6111      "\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2, "", []>, Sched<[]> {
6112  bits<5> Rd;
6113  bits<5> Rn;
6114  bits<5> Rm;
6115  let Inst{31}    = 0;
6116  let Inst{30}    = Q;
6117  let Inst{29}    = U;
6118  let Inst{28-24} = 0b01110;
6119  let Inst{23-22} = size;
6120  let Inst{21}    = 0b0;
6121  let Inst{20-16} = Rm;
6122  let Inst{15}    = 0b1;
6123  let Inst{14-11} = op;
6124  let Inst{10}    = 0b1;
6125  let Inst{9-5}   = Rn;
6126  let Inst{4-0}   = Rd;
6127}
6128
6129
6130// FCVTN (FP16 to FP8)
6131multiclass SIMDThreeSameSizeVectorCvt<string asm> {
6132   def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b01, 0b1110, V64, V64, asm, ".8b",".4h">;
6133   def v16f8 : BaseSIMDThreeVectors<0b1, 0b0, 0b01, 0b1110,  V128, V128, asm, ".16b", ".8h">;
6134}
6135
6136// TODO : Create v16f8 value type
6137// FCVTN, FCVTN2 (FP32 to FP8)
6138multiclass SIMDThreeVectorCvt<string asm> {
6139   def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b00, 0b1110, V64, V128, asm, ".8b", ".4s">;
6140   def 2v16f8 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1110, asm#2, ".16b", ".4s",
6141                                           V128, v16i8, v4f32, null_frag>;
6142}
6143
6144// TODO: Create a new Value Type v8f8 and v16f8
6145multiclass SIMDThreeSameVectorDOT2<string asm> {
6146   def v4f16 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b01, 0b1111, asm, ".4h", ".8b",
6147                                          V64, v4f16, v8i8, null_frag>;
6148   def v8f16 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b01, 0b1111, asm, ".8h", ".16b",
6149                                          V128, v8f16, v16i8, null_frag>;
6150}
6151
6152multiclass SIMDThreeSameVectorDOT4<string asm> {
6153   def v2f32 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b00, 0b1111, asm, ".2s", ".8b",
6154                                          V64, v2f32, v8i8, null_frag>;
6155   def v4f32 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1111, asm, ".4s", ".16b",
6156                                          V128, v4f32, v16i8, null_frag>;
6157}
6158
6159//----------------------------------------------------------------------------
6160// AdvSIMD two register vector instructions.
6161//----------------------------------------------------------------------------
6162
6163let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6164class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6165                            bits<2> size2, RegisterOperand regtype, string asm,
6166                            string dstkind, string srckind, list<dag> pattern>
6167  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6168      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6169      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
6170    Sched<[!if(Q, WriteVq, WriteVd)]> {
6171  bits<5> Rd;
6172  bits<5> Rn;
6173  let Inst{31}    = 0;
6174  let Inst{30}    = Q;
6175  let Inst{29}    = U;
6176  let Inst{28-24} = 0b01110;
6177  let Inst{23-22} = size;
6178  let Inst{21} = 0b1;
6179  let Inst{20-19} = size2;
6180  let Inst{18-17} = 0b00;
6181  let Inst{16-12} = opcode;
6182  let Inst{11-10} = 0b10;
6183  let Inst{9-5}   = Rn;
6184  let Inst{4-0}   = Rd;
6185}
6186
6187let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6188class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6189                                bits<2> size2, RegisterOperand regtype,
6190                                string asm, string dstkind, string srckind,
6191                                list<dag> pattern>
6192  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
6193      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6194      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6195    Sched<[!if(Q, WriteVq, WriteVd)]> {
6196  bits<5> Rd;
6197  bits<5> Rn;
6198  let Inst{31}    = 0;
6199  let Inst{30}    = Q;
6200  let Inst{29}    = U;
6201  let Inst{28-24} = 0b01110;
6202  let Inst{23-22} = size;
6203  let Inst{21} = 0b1;
6204  let Inst{20-19} = size2;
6205  let Inst{18-17} = 0b00;
6206  let Inst{16-12} = opcode;
6207  let Inst{11-10} = 0b10;
6208  let Inst{9-5}   = Rn;
6209  let Inst{4-0}   = Rd;
6210}
6211
6212// Supports B, H, and S element sizes.
6213multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
6214                            SDPatternOperator OpNode> {
6215  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6216                                      asm, ".8b", ".8b",
6217                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6218  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6219                                      asm, ".16b", ".16b",
6220                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6221  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6222                                      asm, ".4h", ".4h",
6223                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6224  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6225                                      asm, ".8h", ".8h",
6226                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6227  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6228                                      asm, ".2s", ".2s",
6229                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6230  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6231                                      asm, ".4s", ".4s",
6232                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6233}
6234
6235class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
6236                            RegisterOperand regtype, string asm, string dstkind,
6237                            string srckind, string amount>
6238  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
6239      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
6240      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
6241    Sched<[WriteVq]> {
6242  bits<5> Rd;
6243  bits<5> Rn;
6244  let Inst{31}    = 0;
6245  let Inst{30}    = Q;
6246  let Inst{29-24} = 0b101110;
6247  let Inst{23-22} = size;
6248  let Inst{21-10} = 0b100001001110;
6249  let Inst{9-5}   = Rn;
6250  let Inst{4-0}   = Rd;
6251}
6252
6253multiclass SIMDVectorLShiftLongBySizeBHS {
6254  let hasSideEffects = 0 in {
6255  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
6256                                             "shll", ".8h",  ".8b", "8">;
6257  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
6258                                             "shll2", ".8h", ".16b", "8">;
6259  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
6260                                             "shll", ".4s",  ".4h", "16">;
6261  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
6262                                             "shll2", ".4s", ".8h", "16">;
6263  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
6264                                             "shll", ".2d",  ".2s", "32">;
6265  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
6266                                             "shll2", ".2d", ".4s", "32">;
6267  }
6268}
6269
6270// Supports all element sizes.
6271multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
6272                             SDPatternOperator OpNode> {
6273  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6274                                      asm, ".4h", ".8b",
6275               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6276  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6277                                      asm, ".8h", ".16b",
6278               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6279  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6280                                      asm, ".2s", ".4h",
6281               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6282  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6283                                      asm, ".4s", ".8h",
6284               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6285  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6286                                      asm, ".1d", ".2s",
6287               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6288  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6289                                      asm, ".2d", ".4s",
6290               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6291}
6292
6293multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
6294                                 SDPatternOperator OpNode> {
6295  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6296                                          asm, ".4h", ".8b",
6297      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
6298                                      (v8i8 V64:$Rn)))]>;
6299  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6300                                          asm, ".8h", ".16b",
6301      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
6302                                      (v16i8 V128:$Rn)))]>;
6303  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6304                                          asm, ".2s", ".4h",
6305      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
6306                                      (v4i16 V64:$Rn)))]>;
6307  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6308                                          asm, ".4s", ".8h",
6309      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
6310                                      (v8i16 V128:$Rn)))]>;
6311  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6312                                          asm, ".1d", ".2s",
6313      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
6314                                      (v2i32 V64:$Rn)))]>;
6315  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6316                                          asm, ".2d", ".4s",
6317      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
6318                                      (v4i32 V128:$Rn)))]>;
6319}
6320
6321// Supports all element sizes, except 1xD.
6322multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
6323                                  SDPatternOperator OpNode> {
6324  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6325                                    asm, ".8b", ".8b",
6326    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
6327  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6328                                    asm, ".16b", ".16b",
6329    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
6330  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6331                                    asm, ".4h", ".4h",
6332    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
6333  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6334                                    asm, ".8h", ".8h",
6335    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
6336  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6337                                    asm, ".2s", ".2s",
6338    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
6339  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6340                                    asm, ".4s", ".4s",
6341    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
6342  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
6343                                    asm, ".2d", ".2d",
6344    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
6345}
6346
6347multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
6348                             SDPatternOperator OpNode = null_frag> {
6349  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6350                                asm, ".8b", ".8b",
6351    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6352  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6353                                asm, ".16b", ".16b",
6354    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6355  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6356                                asm, ".4h", ".4h",
6357    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6358  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6359                                asm, ".8h", ".8h",
6360    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6361  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6362                                asm, ".2s", ".2s",
6363    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6364  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6365                                asm, ".4s", ".4s",
6366    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6367  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6368                                asm, ".2d", ".2d",
6369    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6370}
6371
6372
6373// Supports only B element sizes.
6374multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6375                          SDPatternOperator OpNode> {
6376  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6377                                asm, ".8b", ".8b",
6378                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6379  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6380                                asm, ".16b", ".16b",
6381                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6382
6383}
6384
6385// Supports only B and H element sizes.
6386multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6387                                SDPatternOperator OpNode> {
6388  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6389                                asm, ".8b", ".8b",
6390                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6391  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6392                                asm, ".16b", ".16b",
6393                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6394  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6395                                asm, ".4h", ".4h",
6396                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6397  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6398                                asm, ".8h", ".8h",
6399                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6400}
6401
6402// Supports H, S and D element sizes, uses high bit of the size field
6403// as an extra opcode bit.
6404multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6405                           SDPatternOperator OpNode,
6406                           int fpexceptions = 1> {
6407  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
6408  let Predicates = [HasNEON, HasFullFP16] in {
6409  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6410                                asm, ".4h", ".4h",
6411                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6412  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6413                                asm, ".8h", ".8h",
6414                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6415  } // Predicates = [HasNEON, HasFullFP16]
6416  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6417                                asm, ".2s", ".2s",
6418                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6419  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6420                                asm, ".4s", ".4s",
6421                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6422  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6423                                asm, ".2d", ".2d",
6424                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6425  }
6426}
6427
6428multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6429                                      SDPatternOperator OpNode>
6430    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6431
6432// Supports only S and D element sizes
6433let mayRaiseFPException = 1, Uses = [FPCR] in
6434multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6435                           SDPatternOperator OpNode = null_frag> {
6436
6437  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6438                                asm, ".2s", ".2s",
6439                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6440  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6441                                asm, ".4s", ".4s",
6442                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6443  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6444                                asm, ".2d", ".2d",
6445                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6446}
6447
6448multiclass FRIntNNTVector<bit U, bit op, string asm,
6449                          SDPatternOperator OpNode = null_frag> :
6450           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6451
6452// Supports only S element size.
6453multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6454                           SDPatternOperator OpNode> {
6455  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6456                                asm, ".2s", ".2s",
6457                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6458  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6459                                asm, ".4s", ".4s",
6460                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6461}
6462
6463let mayRaiseFPException = 1, Uses = [FPCR] in
6464multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6465                           SDPatternOperator OpNode> {
6466  let Predicates = [HasNEON, HasFullFP16] in {
6467  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6468                                asm, ".4h", ".4h",
6469                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6470  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6471                                asm, ".8h", ".8h",
6472                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6473  } // Predicates = [HasNEON, HasFullFP16]
6474  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6475                                asm, ".2s", ".2s",
6476                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6477  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6478                                asm, ".4s", ".4s",
6479                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6480  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6481                                asm, ".2d", ".2d",
6482                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6483}
6484
6485let mayRaiseFPException = 1, Uses = [FPCR] in
6486multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6487                           SDPatternOperator OpNode> {
6488  let Predicates = [HasNEON, HasFullFP16] in {
6489  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6490                                asm, ".4h", ".4h",
6491                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6492  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6493                                asm, ".8h", ".8h",
6494                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6495  } // Predicates = [HasNEON, HasFullFP16]
6496  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6497                                asm, ".2s", ".2s",
6498                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6499  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6500                                asm, ".4s", ".4s",
6501                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6502  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6503                                asm, ".2d", ".2d",
6504                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6505}
6506
6507let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6508class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6509                           RegisterOperand inreg, RegisterOperand outreg,
6510                           string asm, string outkind, string inkind,
6511                           list<dag> pattern>
6512  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6513      "{\t$Rd" # outkind # ", $Rn" # inkind #
6514      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6515    Sched<[WriteVq]> {
6516  bits<5> Rd;
6517  bits<5> Rn;
6518  let Inst{31}    = 0;
6519  let Inst{30}    = Q;
6520  let Inst{29}    = U;
6521  let Inst{28-24} = 0b01110;
6522  let Inst{23-22} = size;
6523  let Inst{21-17} = 0b10000;
6524  let Inst{16-12} = opcode;
6525  let Inst{11-10} = 0b10;
6526  let Inst{9-5}   = Rn;
6527  let Inst{4-0}   = Rd;
6528}
6529
6530let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6531class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6532                           RegisterOperand inreg, RegisterOperand outreg,
6533                           string asm, string outkind, string inkind,
6534                           list<dag> pattern>
6535  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6536      "{\t$Rd" # outkind # ", $Rn" # inkind #
6537      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6538    Sched<[WriteVq]> {
6539  bits<5> Rd;
6540  bits<5> Rn;
6541  let Inst{31}    = 0;
6542  let Inst{30}    = Q;
6543  let Inst{29}    = U;
6544  let Inst{28-24} = 0b01110;
6545  let Inst{23-22} = size;
6546  let Inst{21-17} = 0b10000;
6547  let Inst{16-12} = opcode;
6548  let Inst{11-10} = 0b10;
6549  let Inst{9-5}   = Rn;
6550  let Inst{4-0}   = Rd;
6551}
6552
6553multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6554                              SDPatternOperator OpNode> {
6555  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6556                                      asm, ".8b", ".8h",
6557        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6558  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6559                                      asm#"2", ".16b", ".8h", []>;
6560  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6561                                      asm, ".4h", ".4s",
6562        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6563  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6564                                      asm#"2", ".8h", ".4s", []>;
6565  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6566                                      asm, ".2s", ".2d",
6567        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6568  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6569                                      asm#"2", ".4s", ".2d", []>;
6570
6571  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6572            (!cast<Instruction>(NAME # "v16i8")
6573                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6574  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6575            (!cast<Instruction>(NAME # "v8i16")
6576                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6577  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6578            (!cast<Instruction>(NAME # "v4i32")
6579                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6580}
6581
6582//----------------------------------------------------------------------------
6583// FP8 Advanced SIMD two-register miscellaneous
6584//----------------------------------------------------------------------------
6585multiclass SIMDMixedTwoVectorFP8<bits<2>sz, string asm> {
6586  def v8f16 : BaseSIMDMixedTwoVector<0b0, 0b1, sz, 0b10111, V64, V128,
6587                                     asm, ".8h", ".8b", []>;
6588  def 2v8f16 : BaseSIMDMixedTwoVector<0b1, 0b1, sz, 0b10111, V128, V128,
6589                                     asm#2, ".8h", ".16b", []>;
6590}
6591
6592class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6593                           bits<5> opcode, RegisterOperand regtype, string asm,
6594                           string kind, string zero, ValueType dty,
6595                           ValueType sty, SDNode OpNode>
6596  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6597      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6598      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6599      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6600    Sched<[!if(Q, WriteVq, WriteVd)]> {
6601  bits<5> Rd;
6602  bits<5> Rn;
6603  let Inst{31}    = 0;
6604  let Inst{30}    = Q;
6605  let Inst{29}    = U;
6606  let Inst{28-24} = 0b01110;
6607  let Inst{23-22} = size;
6608  let Inst{21} = 0b1;
6609  let Inst{20-19} = size2;
6610  let Inst{18-17} = 0b00;
6611  let Inst{16-12} = opcode;
6612  let Inst{11-10} = 0b10;
6613  let Inst{9-5}   = Rn;
6614  let Inst{4-0}   = Rd;
6615}
6616
6617// Comparisons support all element sizes, except 1xD.
6618multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6619                            SDNode OpNode> {
6620  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6621                                     asm, ".8b", "0",
6622                                     v8i8, v8i8, OpNode>;
6623  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6624                                     asm, ".16b", "0",
6625                                     v16i8, v16i8, OpNode>;
6626  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6627                                     asm, ".4h", "0",
6628                                     v4i16, v4i16, OpNode>;
6629  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6630                                     asm, ".8h", "0",
6631                                     v8i16, v8i16, OpNode>;
6632  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6633                                     asm, ".2s", "0",
6634                                     v2i32, v2i32, OpNode>;
6635  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6636                                     asm, ".4s", "0",
6637                                     v4i32, v4i32, OpNode>;
6638  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6639                                     asm, ".2d", "0",
6640                                     v2i64, v2i64, OpNode>;
6641}
6642
6643// FP Comparisons support only S and D element sizes (and H for v8.2a).
6644multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6645                              string asm, SDNode OpNode> {
6646
6647  let mayRaiseFPException = 1, Uses = [FPCR] in {
6648  let Predicates = [HasNEON, HasFullFP16] in {
6649  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6650                                     asm, ".4h", "0.0",
6651                                     v4i16, v4f16, OpNode>;
6652  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6653                                     asm, ".8h", "0.0",
6654                                     v8i16, v8f16, OpNode>;
6655  } // Predicates = [HasNEON, HasFullFP16]
6656  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6657                                     asm, ".2s", "0.0",
6658                                     v2i32, v2f32, OpNode>;
6659  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6660                                     asm, ".4s", "0.0",
6661                                     v4i32, v4f32, OpNode>;
6662  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6663                                     asm, ".2d", "0.0",
6664                                     v2i64, v2f64, OpNode>;
6665  }
6666
6667  let Predicates = [HasNEON, HasFullFP16] in {
6668  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6669                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6670  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6671                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6672  }
6673  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6674                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6675  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6676                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6677  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6678                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6679  let Predicates = [HasNEON, HasFullFP16] in {
6680  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6681                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6682  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6683                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6684  }
6685  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6686                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6687  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6688                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6689  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6690                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6691}
6692
6693let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6694class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6695                             RegisterOperand outtype, RegisterOperand intype,
6696                             string asm, string VdTy, string VnTy,
6697                             list<dag> pattern>
6698  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6699      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6700    Sched<[WriteVq]> {
6701  bits<5> Rd;
6702  bits<5> Rn;
6703  let Inst{31}    = 0;
6704  let Inst{30}    = Q;
6705  let Inst{29}    = U;
6706  let Inst{28-24} = 0b01110;
6707  let Inst{23-22} = size;
6708  let Inst{21-17} = 0b10000;
6709  let Inst{16-12} = opcode;
6710  let Inst{11-10} = 0b10;
6711  let Inst{9-5}   = Rn;
6712  let Inst{4-0}   = Rd;
6713}
6714
6715let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6716class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6717                             RegisterOperand outtype, RegisterOperand intype,
6718                             string asm, string VdTy, string VnTy,
6719                             list<dag> pattern>
6720  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6721      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6722    Sched<[WriteVq]> {
6723  bits<5> Rd;
6724  bits<5> Rn;
6725  let Inst{31}    = 0;
6726  let Inst{30}    = Q;
6727  let Inst{29}    = U;
6728  let Inst{28-24} = 0b01110;
6729  let Inst{23-22} = size;
6730  let Inst{21-17} = 0b10000;
6731  let Inst{16-12} = opcode;
6732  let Inst{11-10} = 0b10;
6733  let Inst{9-5}   = Rn;
6734  let Inst{4-0}   = Rd;
6735}
6736
6737multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6738  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6739                                    asm, ".4s", ".4h", []>;
6740  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6741                                    asm#"2", ".4s", ".8h", []>;
6742  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6743                                    asm, ".2d", ".2s", []>;
6744  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6745                                    asm#"2", ".2d", ".4s", []>;
6746}
6747
6748multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6749  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6750                                    asm, ".4h", ".4s", []>;
6751  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6752                                    asm#"2", ".8h", ".4s", []>;
6753  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6754                                    asm, ".2s", ".2d", []>;
6755  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6756                                    asm#"2", ".4s", ".2d", []>;
6757}
6758
6759multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6760                                     Intrinsic OpNode> {
6761  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6762                                     asm, ".2s", ".2d",
6763                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6764  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6765                                    asm#"2", ".4s", ".2d", []>;
6766
6767  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6768            (!cast<Instruction>(NAME # "v4f32")
6769                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6770}
6771
6772//----------------------------------------------------------------------------
6773// AdvSIMD three register different-size vector instructions.
6774//----------------------------------------------------------------------------
6775
6776let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6777class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6778                      RegisterOperand outtype, RegisterOperand intype1,
6779                      RegisterOperand intype2, string asm,
6780                      string outkind, string inkind1, string inkind2,
6781                      list<dag> pattern>
6782  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6783      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6784      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6785    Sched<[WriteVq]> {
6786  bits<5> Rd;
6787  bits<5> Rn;
6788  bits<5> Rm;
6789  let Inst{31}    = 0;
6790  let Inst{30}    = size{0};
6791  let Inst{29}    = U;
6792  let Inst{28-24} = 0b01110;
6793  let Inst{23-22} = size{2-1};
6794  let Inst{21}    = 1;
6795  let Inst{20-16} = Rm;
6796  let Inst{15-12} = opcode;
6797  let Inst{11-10} = 0b00;
6798  let Inst{9-5}   = Rn;
6799  let Inst{4-0}   = Rd;
6800}
6801
6802let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6803class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6804                      RegisterOperand outtype, RegisterOperand intype1,
6805                      RegisterOperand intype2, string asm,
6806                      string outkind, string inkind1, string inkind2,
6807                      list<dag> pattern>
6808  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6809      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6810      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6811    Sched<[WriteVq]> {
6812  bits<5> Rd;
6813  bits<5> Rn;
6814  bits<5> Rm;
6815  let Inst{31}    = 0;
6816  let Inst{30}    = size{0};
6817  let Inst{29}    = U;
6818  let Inst{28-24} = 0b01110;
6819  let Inst{23-22} = size{2-1};
6820  let Inst{21}    = 1;
6821  let Inst{20-16} = Rm;
6822  let Inst{15-12} = opcode;
6823  let Inst{11-10} = 0b00;
6824  let Inst{9-5}   = Rn;
6825  let Inst{4-0}   = Rd;
6826}
6827
6828// FIXME: TableGen doesn't know how to deal with expanded types that also
6829//        change the element count (in this case, placing the results in
6830//        the high elements of the result register rather than the low
6831//        elements). Until that's fixed, we can't code-gen those.
6832multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6833                                    Intrinsic IntOp> {
6834  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6835                                                  V64, V128, V128,
6836                                                  asm, ".8b", ".8h", ".8h",
6837     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6838  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6839                                                  V128, V128, V128,
6840                                                  asm#"2", ".16b", ".8h", ".8h",
6841     []>;
6842  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6843                                                  V64, V128, V128,
6844                                                  asm, ".4h", ".4s", ".4s",
6845     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6846  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6847                                                  V128, V128, V128,
6848                                                  asm#"2", ".8h", ".4s", ".4s",
6849     []>;
6850  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6851                                                  V64, V128, V128,
6852                                                  asm, ".2s", ".2d", ".2d",
6853     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6854  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6855                                                  V128, V128, V128,
6856                                                  asm#"2", ".4s", ".2d", ".2d",
6857     []>;
6858
6859
6860  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6861  // a version attached to an instruction.
6862  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6863                                                   (v8i16 V128:$Rm))),
6864            (!cast<Instruction>(NAME # "v8i16_v16i8")
6865                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6866                V128:$Rn, V128:$Rm)>;
6867  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6868                                                    (v4i32 V128:$Rm))),
6869            (!cast<Instruction>(NAME # "v4i32_v8i16")
6870                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6871                V128:$Rn, V128:$Rm)>;
6872  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6873                                                    (v2i64 V128:$Rm))),
6874            (!cast<Instruction>(NAME # "v2i64_v4i32")
6875                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6876                V128:$Rn, V128:$Rm)>;
6877}
6878
6879multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6880                                      SDPatternOperator OpNode> {
6881  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6882                                            V128, V64, V64,
6883                                            asm, ".8h", ".8b", ".8b",
6884      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6885  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6886                                            V128, V128, V128,
6887                                            asm#"2", ".8h", ".16b", ".16b", []>;
6888  let Predicates = [HasAES] in {
6889    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6890                                              V128, V64, V64,
6891                                              asm, ".1q", ".1d", ".1d",
6892        [(set (v16i8 V128:$Rd), (OpNode (v1i64 V64:$Rn), (v1i64 V64:$Rm)))]>;
6893    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6894                                              V128, V128, V128,
6895                                              asm#"2", ".1q", ".2d", ".2d",
6896        [(set (v16i8 V128:$Rd), (OpNode (extract_high_v2i64 (v2i64 V128:$Rn)),
6897                                        (extract_high_v2i64 (v2i64 V128:$Rm))))]>;
6898  }
6899
6900  def : Pat<(v8i16 (OpNode (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6901                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6902      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6903}
6904
6905multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6906                                 SDPatternOperator OpNode> {
6907  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6908                                                  V128, V64, V64,
6909                                                  asm, ".4s", ".4h", ".4h",
6910      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6911  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6912                                                  V128, V128, V128,
6913                                                  asm#"2", ".4s", ".8h", ".8h",
6914      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6915                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6916  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6917                                                  V128, V64, V64,
6918                                                  asm, ".2d", ".2s", ".2s",
6919      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6920  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6921                                                  V128, V128, V128,
6922                                                  asm#"2", ".2d", ".4s", ".4s",
6923      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6924                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6925}
6926
6927multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6928                                  SDPatternOperator OpNode = null_frag> {
6929  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6930                                                  V128, V64, V64,
6931                                                  asm, ".8h", ".8b", ".8b",
6932      [(set (v8i16 V128:$Rd),
6933            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6934  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6935                                                 V128, V128, V128,
6936                                                 asm#"2", ".8h", ".16b", ".16b",
6937      [(set (v8i16 V128:$Rd),
6938            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6939                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
6940  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6941                                                  V128, V64, V64,
6942                                                  asm, ".4s", ".4h", ".4h",
6943      [(set (v4i32 V128:$Rd),
6944            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6945  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6946                                                  V128, V128, V128,
6947                                                  asm#"2", ".4s", ".8h", ".8h",
6948      [(set (v4i32 V128:$Rd),
6949            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6950                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6951  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6952                                                  V128, V64, V64,
6953                                                  asm, ".2d", ".2s", ".2s",
6954      [(set (v2i64 V128:$Rd),
6955            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6956  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6957                                                  V128, V128, V128,
6958                                                  asm#"2", ".2d", ".4s", ".4s",
6959      [(set (v2i64 V128:$Rd),
6960            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6961                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6962}
6963
6964multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6965                                          string asm,
6966                                          SDPatternOperator OpNode> {
6967  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6968                                                  V128, V64, V64,
6969                                                  asm, ".8h", ".8b", ".8b",
6970    [(set (v8i16 V128:$dst),
6971          (add (v8i16 V128:$Rd),
6972               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6973  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6974                                                 V128, V128, V128,
6975                                                 asm#"2", ".8h", ".16b", ".16b",
6976    [(set (v8i16 V128:$dst),
6977          (add (v8i16 V128:$Rd),
6978               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6979                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
6980  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6981                                                  V128, V64, V64,
6982                                                  asm, ".4s", ".4h", ".4h",
6983    [(set (v4i32 V128:$dst),
6984          (add (v4i32 V128:$Rd),
6985               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6986  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6987                                                  V128, V128, V128,
6988                                                  asm#"2", ".4s", ".8h", ".8h",
6989    [(set (v4i32 V128:$dst),
6990          (add (v4i32 V128:$Rd),
6991               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6992                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
6993  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6994                                                  V128, V64, V64,
6995                                                  asm, ".2d", ".2s", ".2s",
6996    [(set (v2i64 V128:$dst),
6997          (add (v2i64 V128:$Rd),
6998               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6999  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7000                                                  V128, V128, V128,
7001                                                  asm#"2", ".2d", ".4s", ".4s",
7002    [(set (v2i64 V128:$dst),
7003          (add (v2i64 V128:$Rd),
7004               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7005                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
7006}
7007
7008multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
7009                                  SDPatternOperator OpNode = null_frag> {
7010  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7011                                                  V128, V64, V64,
7012                                                  asm, ".8h", ".8b", ".8b",
7013      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7014  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7015                                                 V128, V128, V128,
7016                                                 asm#"2", ".8h", ".16b", ".16b",
7017      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7018                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7019  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7020                                                  V128, V64, V64,
7021                                                  asm, ".4s", ".4h", ".4h",
7022      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7023  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7024                                                  V128, V128, V128,
7025                                                  asm#"2", ".4s", ".8h", ".8h",
7026      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7027                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7028  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7029                                                  V128, V64, V64,
7030                                                  asm, ".2d", ".2s", ".2s",
7031      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7032  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7033                                                  V128, V128, V128,
7034                                                  asm#"2", ".2d", ".4s", ".4s",
7035      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7036                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7037}
7038
7039multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
7040                                      string asm,
7041                                      SDPatternOperator OpNode> {
7042  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7043                                                  V128, V64, V64,
7044                                                  asm, ".8h", ".8b", ".8b",
7045    [(set (v8i16 V128:$dst),
7046          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7047  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7048                                                 V128, V128, V128,
7049                                                 asm#"2", ".8h", ".16b", ".16b",
7050    [(set (v8i16 V128:$dst),
7051          (OpNode (v8i16 V128:$Rd),
7052                  (extract_high_v16i8 (v16i8 V128:$Rn)),
7053                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7054  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7055                                                  V128, V64, V64,
7056                                                  asm, ".4s", ".4h", ".4h",
7057    [(set (v4i32 V128:$dst),
7058          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7059  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7060                                                  V128, V128, V128,
7061                                                  asm#"2", ".4s", ".8h", ".8h",
7062    [(set (v4i32 V128:$dst),
7063          (OpNode (v4i32 V128:$Rd),
7064                  (extract_high_v8i16 (v8i16 V128:$Rn)),
7065                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7066  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7067                                                  V128, V64, V64,
7068                                                  asm, ".2d", ".2s", ".2s",
7069    [(set (v2i64 V128:$dst),
7070          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7071  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7072                                                  V128, V128, V128,
7073                                                  asm#"2", ".2d", ".4s", ".4s",
7074    [(set (v2i64 V128:$dst),
7075          (OpNode (v2i64 V128:$Rd),
7076                  (extract_high_v4i32 (v4i32 V128:$Rn)),
7077                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7078}
7079
7080multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
7081                                           SDPatternOperator Accum> {
7082  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7083                                                  V128, V64, V64,
7084                                                  asm, ".4s", ".4h", ".4h",
7085    [(set (v4i32 V128:$dst),
7086          (Accum (v4i32 V128:$Rd),
7087                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7088                                                (v4i16 V64:$Rm)))))]>;
7089  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7090                                                  V128, V128, V128,
7091                                                  asm#"2", ".4s", ".8h", ".8h",
7092    [(set (v4i32 V128:$dst),
7093          (Accum (v4i32 V128:$Rd),
7094                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
7095                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7096  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7097                                                  V128, V64, V64,
7098                                                  asm, ".2d", ".2s", ".2s",
7099    [(set (v2i64 V128:$dst),
7100          (Accum (v2i64 V128:$Rd),
7101                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
7102                                                (v2i32 V64:$Rm)))))]>;
7103  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7104                                                  V128, V128, V128,
7105                                                  asm#"2", ".2d", ".4s", ".4s",
7106    [(set (v2i64 V128:$dst),
7107          (Accum (v2i64 V128:$Rd),
7108                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
7109                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7110}
7111
7112multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
7113                                  SDPatternOperator OpNode> {
7114  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7115                                                  V128, V128, V64,
7116                                                  asm, ".8h", ".8h", ".8b",
7117       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
7118  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7119                                                  V128, V128, V128,
7120                                                  asm#"2", ".8h", ".8h", ".16b",
7121       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7122                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7123  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7124                                                  V128, V128, V64,
7125                                                  asm, ".4s", ".4s", ".4h",
7126       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
7127  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7128                                                  V128, V128, V128,
7129                                                  asm#"2", ".4s", ".4s", ".8h",
7130       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7131                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7132  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7133                                                  V128, V128, V64,
7134                                                  asm, ".2d", ".2d", ".2s",
7135       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
7136  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7137                                                  V128, V128, V128,
7138                                                  asm#"2", ".2d", ".2d", ".4s",
7139       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7140                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7141}
7142
7143//----------------------------------------------------------------------------
7144// AdvSIMD bitwise extract from vector
7145//----------------------------------------------------------------------------
7146
7147class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
7148                             string asm, string kind>
7149  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
7150      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
7151      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
7152      [(set (vty regtype:$Rd),
7153            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
7154    Sched<[!if(size, WriteVq, WriteVd)]> {
7155  bits<5> Rd;
7156  bits<5> Rn;
7157  bits<5> Rm;
7158  bits<4> imm;
7159  let Inst{31}    = 0;
7160  let Inst{30}    = size;
7161  let Inst{29-21} = 0b101110000;
7162  let Inst{20-16} = Rm;
7163  let Inst{15}    = 0;
7164  let Inst{14-11} = imm;
7165  let Inst{10}    = 0;
7166  let Inst{9-5}   = Rn;
7167  let Inst{4-0}   = Rd;
7168}
7169
7170
7171multiclass SIMDBitwiseExtract<string asm> {
7172  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
7173    let imm{3} = 0;
7174  }
7175  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
7176}
7177
7178//----------------------------------------------------------------------------
7179// AdvSIMD zip vector
7180//----------------------------------------------------------------------------
7181
7182class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
7183                        string asm, string kind, SDNode OpNode, ValueType valty>
7184  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7185      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
7186      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
7187      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
7188    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
7189  bits<5> Rd;
7190  bits<5> Rn;
7191  bits<5> Rm;
7192  let Inst{31}    = 0;
7193  let Inst{30}    = size{0};
7194  let Inst{29-24} = 0b001110;
7195  let Inst{23-22} = size{2-1};
7196  let Inst{21}    = 0;
7197  let Inst{20-16} = Rm;
7198  let Inst{15}    = 0;
7199  let Inst{14-12} = opc;
7200  let Inst{11-10} = 0b10;
7201  let Inst{9-5}   = Rn;
7202  let Inst{4-0}   = Rd;
7203}
7204
7205multiclass SIMDZipVector<bits<3>opc, string asm,
7206                         SDNode OpNode> {
7207  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
7208      asm, ".8b", OpNode, v8i8>;
7209  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
7210      asm, ".16b", OpNode, v16i8>;
7211  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
7212      asm, ".4h", OpNode, v4i16>;
7213  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
7214      asm, ".8h", OpNode, v8i16>;
7215  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
7216      asm, ".2s", OpNode, v2i32>;
7217  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
7218      asm, ".4s", OpNode, v4i32>;
7219  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
7220      asm, ".2d", OpNode, v2i64>;
7221
7222  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
7223        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7224  def : Pat<(v4bf16 (OpNode V64:$Rn, V64:$Rm)),
7225        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7226  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
7227        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7228  def : Pat<(v8bf16 (OpNode V128:$Rn, V128:$Rm)),
7229        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7230  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
7231        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
7232  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
7233        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
7234  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
7235        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
7236}
7237
7238//----------------------------------------------------------------------------
7239// AdvSIMD three register scalar instructions
7240//----------------------------------------------------------------------------
7241
7242let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7243class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
7244                        RegisterClass regtype, string asm,
7245                        list<dag> pattern>
7246  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7247      "\t$Rd, $Rn, $Rm", "", pattern>,
7248    Sched<[WriteVd]> {
7249  bits<5> Rd;
7250  bits<5> Rn;
7251  bits<5> Rm;
7252  let Inst{31-30} = 0b01;
7253  let Inst{29}    = U;
7254  let Inst{28-24} = 0b11110;
7255  let Inst{23-21} = size;
7256  let Inst{20-16} = Rm;
7257  let Inst{15-11} = opcode;
7258  let Inst{10}    = 1;
7259  let Inst{9-5}   = Rn;
7260  let Inst{4-0}   = Rd;
7261}
7262
7263let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7264class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
7265                        dag oops, dag iops, string asm,
7266            list<dag> pattern>
7267  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
7268    Sched<[WriteVd]> {
7269  bits<5> Rd;
7270  bits<5> Rn;
7271  bits<5> Rm;
7272  let Inst{31-30} = 0b01;
7273  let Inst{29}    = U;
7274  let Inst{28-24} = 0b11110;
7275  let Inst{23-22} = size;
7276  let Inst{21}    = R;
7277  let Inst{20-16} = Rm;
7278  let Inst{15-11} = opcode;
7279  let Inst{10}    = 1;
7280  let Inst{9-5}   = Rn;
7281  let Inst{4-0}   = Rd;
7282}
7283
7284multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
7285                            SDPatternOperator OpNode> {
7286  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7287    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7288}
7289
7290multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
7291                               SDPatternOperator OpNode> {
7292  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7293    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7294  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
7295  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7296  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
7297
7298  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7299            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
7300  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
7301            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
7302}
7303
7304multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
7305                             SDPatternOperator OpNode> {
7306  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
7307                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7308  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7309}
7310
7311multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
7312  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
7313                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
7314                                     asm, []>;
7315  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
7316                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
7317                                     asm, []>;
7318}
7319
7320multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
7321                             SDPatternOperator OpNode = null_frag,
7322                             Predicate pred = HasNEON> {
7323  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7324    let Predicates = [pred] in {
7325    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7326      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7327    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7328      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7329    }
7330    let Predicates = [pred, HasFullFP16] in {
7331    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7332      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
7333    }
7334  }
7335
7336  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7337            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7338}
7339
7340multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
7341                                SDPatternOperator OpNode = null_frag> {
7342  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7343    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7344      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7345    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7346      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
7347    let Predicates = [HasNEON, HasFullFP16] in {
7348    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7349      []>;
7350    } // Predicates = [HasNEON, HasFullFP16]
7351  }
7352
7353  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7354            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7355}
7356
7357class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
7358              dag oops, dag iops, string asm, string cstr, list<dag> pat>
7359  : I<oops, iops, asm,
7360      "\t$Rd, $Rn, $Rm", cstr, pat>,
7361    Sched<[WriteVd]> {
7362  bits<5> Rd;
7363  bits<5> Rn;
7364  bits<5> Rm;
7365  let Inst{31-30} = 0b01;
7366  let Inst{29}    = U;
7367  let Inst{28-24} = 0b11110;
7368  let Inst{23-22} = size;
7369  let Inst{21}    = 1;
7370  let Inst{20-16} = Rm;
7371  let Inst{15-11} = opcode;
7372  let Inst{10}    = 0;
7373  let Inst{9-5}   = Rn;
7374  let Inst{4-0}   = Rd;
7375}
7376
7377let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7378multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
7379                                  SDPatternOperator OpNode = null_frag> {
7380  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7381                                      (outs FPR32:$Rd),
7382                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7383  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7384                                      (outs FPR64:$Rd),
7385                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7386            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7387}
7388
7389let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7390multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7391                                  SDPatternOperator OpNode = null_frag> {
7392  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7393                                      (outs FPR32:$dst),
7394                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7395                                      asm, "$Rd = $dst", []>;
7396  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7397                                      (outs FPR64:$dst),
7398                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7399                                      asm, "$Rd = $dst",
7400            [(set (i64 FPR64:$dst),
7401                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7402}
7403
7404//----------------------------------------------------------------------------
7405// AdvSIMD two register scalar instructions
7406//----------------------------------------------------------------------------
7407
7408let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7409class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7410                        RegisterClass regtype, RegisterClass regtype2,
7411                        string asm, list<dag> pat>
7412  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7413      "\t$Rd, $Rn", "", pat>,
7414    Sched<[WriteVd]> {
7415  bits<5> Rd;
7416  bits<5> Rn;
7417  let Inst{31-30} = 0b01;
7418  let Inst{29}    = U;
7419  let Inst{28-24} = 0b11110;
7420  let Inst{23-22} = size;
7421  let Inst{21} = 0b1;
7422  let Inst{20-19} = size2;
7423  let Inst{18-17} = 0b00;
7424  let Inst{16-12} = opcode;
7425  let Inst{11-10} = 0b10;
7426  let Inst{9-5}   = Rn;
7427  let Inst{4-0}   = Rd;
7428}
7429
7430let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7431class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7432                        RegisterClass regtype, RegisterClass regtype2,
7433                        string asm, list<dag> pat>
7434  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7435      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7436    Sched<[WriteVd]> {
7437  bits<5> Rd;
7438  bits<5> Rn;
7439  let Inst{31-30} = 0b01;
7440  let Inst{29}    = U;
7441  let Inst{28-24} = 0b11110;
7442  let Inst{23-22} = size;
7443  let Inst{21-17} = 0b10000;
7444  let Inst{16-12} = opcode;
7445  let Inst{11-10} = 0b10;
7446  let Inst{9-5}   = Rn;
7447  let Inst{4-0}   = Rd;
7448}
7449
7450
7451let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7452class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7453                        RegisterClass regtype, string asm, string zero>
7454  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7455      "\t$Rd, $Rn, #" # zero, "", []>,
7456    Sched<[WriteVd]> {
7457  bits<5> Rd;
7458  bits<5> Rn;
7459  let Inst{31-30} = 0b01;
7460  let Inst{29}    = U;
7461  let Inst{28-24} = 0b11110;
7462  let Inst{23-22} = size;
7463  let Inst{21} = 0b1;
7464  let Inst{20-19} = size2;
7465  let Inst{18-17} = 0b00;
7466  let Inst{16-12} = opcode;
7467  let Inst{11-10} = 0b10;
7468  let Inst{9-5}   = Rn;
7469  let Inst{4-0}   = Rd;
7470}
7471
7472let mayRaiseFPException = 1, Uses = [FPCR] in
7473class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7474  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7475     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7476    Sched<[WriteVd]> {
7477  bits<5> Rd;
7478  bits<5> Rn;
7479  let Inst{31-17} = 0b011111100110000;
7480  let Inst{16-12} = opcode;
7481  let Inst{11-10} = 0b10;
7482  let Inst{9-5}   = Rn;
7483  let Inst{4-0}   = Rd;
7484}
7485
7486multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7487                             SDPatternOperator OpNode> {
7488  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7489
7490  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7491            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7492}
7493
7494multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7495                              SDPatternOperator OpNode> {
7496  let mayRaiseFPException = 1, Uses = [FPCR] in {
7497  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7498  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7499  let Predicates = [HasNEON, HasFullFP16] in {
7500  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7501  }
7502  }
7503
7504  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7505                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7506  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7507                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7508  let Predicates = [HasNEON, HasFullFP16] in {
7509  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7510                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7511  }
7512
7513  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7514            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7515}
7516
7517multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7518                          SDPatternOperator OpNode = null_frag,
7519                          list<Predicate> preds = []> {
7520  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7521    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7522
7523  let Predicates = preds in {
7524  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7525            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7526  }
7527}
7528
7529let mayRaiseFPException = 1, Uses = [FPCR] in
7530multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7531                           Predicate pred = HasNEON> {
7532  let Predicates = [pred] in {
7533  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7534  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7535  }
7536  let Predicates = [pred, HasFullFP16] in {
7537  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7538  }
7539}
7540
7541let mayRaiseFPException = 1, Uses = [FPCR] in
7542multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7543                              SDPatternOperator OpNode> {
7544  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7545                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7546  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7547                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7548  let Predicates = [HasNEON, HasFullFP16] in {
7549  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7550                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7551  }
7552}
7553
7554multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7555                             SDPatternOperator OpNode = null_frag> {
7556  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7557    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7558           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7559    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7560           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7561    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7562    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7563  }
7564
7565  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7566            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7567}
7568
7569multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7570                                 Intrinsic OpNode> {
7571  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7572    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7573        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7574    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7575        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7576    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7577    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7578  }
7579
7580  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7581            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7582}
7583
7584
7585
7586let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7587multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7588                                 SDPatternOperator OpNode = null_frag> {
7589  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7590        [(set (f32 FPR32:$Rd), (OpNode (f64 FPR64:$Rn)))]>;
7591  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7592  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7593}
7594
7595//----------------------------------------------------------------------------
7596// AdvSIMD scalar pairwise instructions
7597//----------------------------------------------------------------------------
7598
7599let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7600class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7601                        RegisterOperand regtype, RegisterOperand vectype,
7602                        string asm, string kind>
7603  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7604      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7605    Sched<[WriteVd]> {
7606  bits<5> Rd;
7607  bits<5> Rn;
7608  let Inst{31-30} = 0b01;
7609  let Inst{29}    = U;
7610  let Inst{28-24} = 0b11110;
7611  let Inst{23-22} = size;
7612  let Inst{21-17} = 0b11000;
7613  let Inst{16-12} = opcode;
7614  let Inst{11-10} = 0b10;
7615  let Inst{9-5}   = Rn;
7616  let Inst{4-0}   = Rd;
7617}
7618
7619multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7620  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7621                                      asm, ".2d">;
7622}
7623
7624let mayRaiseFPException = 1, Uses = [FPCR] in
7625multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7626  let Predicates = [HasNEON, HasFullFP16] in {
7627  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7628                                      asm, ".2h">;
7629  }
7630  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7631                                      asm, ".2s">;
7632  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7633                                      asm, ".2d">;
7634}
7635
7636//----------------------------------------------------------------------------
7637// AdvSIMD across lanes instructions
7638//----------------------------------------------------------------------------
7639
7640let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7641class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7642                          RegisterClass regtype, RegisterOperand vectype,
7643                          string asm, string kind, list<dag> pattern>
7644  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7645      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7646    Sched<[!if(Q, WriteVq, WriteVd)]> {
7647  bits<5> Rd;
7648  bits<5> Rn;
7649  let Inst{31}    = 0;
7650  let Inst{30}    = Q;
7651  let Inst{29}    = U;
7652  let Inst{28-24} = 0b01110;
7653  let Inst{23-22} = size;
7654  let Inst{21-17} = 0b11000;
7655  let Inst{16-12} = opcode;
7656  let Inst{11-10} = 0b10;
7657  let Inst{9-5}   = Rn;
7658  let Inst{4-0}   = Rd;
7659}
7660
7661multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7662                              string asm> {
7663  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7664                                   asm, ".8b", []>;
7665  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7666                                   asm, ".16b", []>;
7667  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7668                                   asm, ".4h", []>;
7669  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7670                                   asm, ".8h", []>;
7671  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7672                                   asm, ".4s", []>;
7673}
7674
7675multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7676  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7677                                   asm, ".8b", []>;
7678  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7679                                   asm, ".16b", []>;
7680  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7681                                   asm, ".4h", []>;
7682  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7683                                   asm, ".8h", []>;
7684  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7685                                   asm, ".4s", []>;
7686}
7687
7688let mayRaiseFPException = 1, Uses = [FPCR] in
7689multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7690                            SDPatternOperator intOp> {
7691  let Predicates = [HasNEON, HasFullFP16] in {
7692  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7693                                   asm, ".4h",
7694        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7695  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7696                                   asm, ".8h",
7697        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7698  } // Predicates = [HasNEON, HasFullFP16]
7699  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7700                                   asm, ".4s",
7701        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7702}
7703
7704//----------------------------------------------------------------------------
7705// AdvSIMD INS/DUP instructions
7706//----------------------------------------------------------------------------
7707
7708// FIXME: There has got to be a better way to factor these. ugh.
7709
7710class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7711                     string operands, string constraints, list<dag> pattern>
7712  : I<outs, ins, asm, operands, constraints, pattern>,
7713    Sched<[!if(Q, WriteVq, WriteVd)]> {
7714  bits<5> Rd;
7715  bits<5> Rn;
7716  let Inst{31} = 0;
7717  let Inst{30} = Q;
7718  let Inst{29} = op;
7719  let Inst{28-21} = 0b01110000;
7720  let Inst{15} = 0;
7721  let Inst{10} = 1;
7722  let Inst{9-5} = Rn;
7723  let Inst{4-0} = Rd;
7724}
7725
7726class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7727                      RegisterOperand vecreg, RegisterClass regtype>
7728  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7729                   "{\t$Rd" # size # ", $Rn" #
7730                   "|" # size # "\t$Rd, $Rn}", "",
7731                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7732  let Inst{20-16} = imm5;
7733  let Inst{14-11} = 0b0001;
7734}
7735
7736class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7737                         ValueType vectype, ValueType insreg,
7738                         RegisterOperand vecreg, Operand idxtype,
7739                         SDNode OpNode>
7740  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7741                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7742                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7743                 [(set (vectype vecreg:$Rd),
7744                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7745  let Inst{14-11} = 0b0000;
7746}
7747
7748class SIMDDup64FromElement
7749  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7750                       VectorIndexD, AArch64duplane64> {
7751  bits<1> idx;
7752  let Inst{20} = idx;
7753  let Inst{19-16} = 0b1000;
7754}
7755
7756class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7757                           RegisterOperand vecreg>
7758  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7759                       VectorIndexS, AArch64duplane32> {
7760  bits<2> idx;
7761  let Inst{20-19} = idx;
7762  let Inst{18-16} = 0b100;
7763}
7764
7765class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7766                           RegisterOperand vecreg>
7767  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7768                       VectorIndexH, AArch64duplane16> {
7769  bits<3> idx;
7770  let Inst{20-18} = idx;
7771  let Inst{17-16} = 0b10;
7772}
7773
7774class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7775                          RegisterOperand vecreg>
7776  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7777                       VectorIndexB, AArch64duplane8> {
7778  bits<4> idx;
7779  let Inst{20-17} = idx;
7780  let Inst{16} = 1;
7781}
7782
7783class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7784                  Operand idxtype, string asm, list<dag> pattern>
7785  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7786                   "{\t$Rd, $Rn" # size # "$idx" #
7787                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7788  let Inst{14-11} = imm4;
7789}
7790
7791class SIMDSMov<bit Q, string size, RegisterClass regtype,
7792               Operand idxtype>
7793  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7794class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7795               Operand idxtype>
7796  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7797      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7798
7799class SIMDMovAlias<string asm, string size, Instruction inst,
7800                   RegisterClass regtype, Operand idxtype>
7801    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7802                    "|" # size # "\t$dst, $src$idx}",
7803                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7804
7805multiclass SMov {
7806  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7807  // streaming mode.
7808  let Predicates = [HasNEONorSME] in {
7809    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7810      let Inst{20-16} = 0b00001;
7811    }
7812    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7813      let Inst{20-16} = 0b00001;
7814    }
7815    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7816      let Inst{20-16} = 0b00010;
7817    }
7818    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7819      let Inst{20-16} = 0b00010;
7820    }
7821    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7822      let Inst{20-16} = 0b00100;
7823    }
7824  }
7825  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7826    bits<4> idx;
7827    let Inst{20-17} = idx;
7828    let Inst{16} = 1;
7829  }
7830  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7831    bits<4> idx;
7832    let Inst{20-17} = idx;
7833    let Inst{16} = 1;
7834  }
7835  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7836    bits<3> idx;
7837    let Inst{20-18} = idx;
7838    let Inst{17-16} = 0b10;
7839  }
7840  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7841    bits<3> idx;
7842    let Inst{20-18} = idx;
7843    let Inst{17-16} = 0b10;
7844  }
7845  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7846    bits<2> idx;
7847    let Inst{20-19} = idx;
7848    let Inst{18-16} = 0b100;
7849  }
7850}
7851
7852multiclass UMov {
7853  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7854  // streaming mode.
7855  let Predicates = [HasNEONorSME] in {
7856    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7857      let Inst{20-16} = 0b00001;
7858    }
7859    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7860      let Inst{20-16} = 0b00010;
7861    }
7862    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7863      let Inst{20-16} = 0b00100;
7864    }
7865    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7866      let Inst{20-16} = 0b01000;
7867    }
7868    def : SIMDMovAlias<"mov", ".s",
7869                       !cast<Instruction>(NAME # vi32_idx0),
7870                       GPR32, VectorIndex0>;
7871    def : SIMDMovAlias<"mov", ".d",
7872                       !cast<Instruction>(NAME # vi64_idx0),
7873                       GPR64, VectorIndex0>;
7874  }
7875  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7876    bits<4> idx;
7877    let Inst{20-17} = idx;
7878    let Inst{16} = 1;
7879  }
7880  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7881    bits<3> idx;
7882    let Inst{20-18} = idx;
7883    let Inst{17-16} = 0b10;
7884  }
7885  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7886    bits<2> idx;
7887    let Inst{20-19} = idx;
7888    let Inst{18-16} = 0b100;
7889  }
7890  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7891    bits<1> idx;
7892    let Inst{20} = idx;
7893    let Inst{19-16} = 0b1000;
7894  }
7895  def : SIMDMovAlias<"mov", ".s",
7896                     !cast<Instruction>(NAME#"vi32"),
7897                     GPR32, VectorIndexS>;
7898  def : SIMDMovAlias<"mov", ".d",
7899                     !cast<Instruction>(NAME#"vi64"),
7900                     GPR64, VectorIndexD>;
7901}
7902
7903class SIMDInsFromMain<string size, ValueType vectype,
7904                      RegisterClass regtype, Operand idxtype>
7905  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7906                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7907                   "{\t$Rd" # size # "$idx, $Rn" #
7908                   "|" # size # "\t$Rd$idx, $Rn}",
7909                   "$Rd = $dst",
7910            [(set V128:$dst,
7911              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7912  let Inst{14-11} = 0b0011;
7913}
7914
7915class SIMDInsFromElement<string size, ValueType vectype,
7916                         ValueType elttype, Operand idxtype>
7917  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7918                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7919                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7920                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7921                   "$Rd = $dst",
7922         [(set V128:$dst,
7923               (vector_insert
7924                 (vectype V128:$Rd),
7925                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7926                 idxtype:$idx))]>;
7927
7928class SIMDInsMainMovAlias<string size, Instruction inst,
7929                          RegisterClass regtype, Operand idxtype>
7930    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7931                        "|" # size #"\t$dst$idx, $src}",
7932                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7933class SIMDInsElementMovAlias<string size, Instruction inst,
7934                             Operand idxtype>
7935    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7936                      # "|" # size #"\t$dst$idx, $src$idx2}",
7937                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7938
7939
7940multiclass SIMDIns {
7941  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7942    bits<4> idx;
7943    let Inst{20-17} = idx;
7944    let Inst{16} = 1;
7945  }
7946  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7947    bits<3> idx;
7948    let Inst{20-18} = idx;
7949    let Inst{17-16} = 0b10;
7950  }
7951  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7952    bits<2> idx;
7953    let Inst{20-19} = idx;
7954    let Inst{18-16} = 0b100;
7955  }
7956  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7957    bits<1> idx;
7958    let Inst{20} = idx;
7959    let Inst{19-16} = 0b1000;
7960  }
7961
7962  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7963    bits<4> idx;
7964    bits<4> idx2;
7965    let Inst{20-17} = idx;
7966    let Inst{16} = 1;
7967    let Inst{14-11} = idx2;
7968  }
7969  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7970    bits<3> idx;
7971    bits<3> idx2;
7972    let Inst{20-18} = idx;
7973    let Inst{17-16} = 0b10;
7974    let Inst{14-12} = idx2;
7975    let Inst{11} = {?};
7976  }
7977  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7978    bits<2> idx;
7979    bits<2> idx2;
7980    let Inst{20-19} = idx;
7981    let Inst{18-16} = 0b100;
7982    let Inst{14-13} = idx2;
7983    let Inst{12-11} = {?,?};
7984  }
7985  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7986    bits<1> idx;
7987    bits<1> idx2;
7988    let Inst{20} = idx;
7989    let Inst{19-16} = 0b1000;
7990    let Inst{14} = idx2;
7991    let Inst{13-11} = {?,?,?};
7992  }
7993
7994  // For all forms of the INS instruction, the "mov" mnemonic is the
7995  // preferred alias. Why they didn't just call the instruction "mov" in
7996  // the first place is a very good question indeed...
7997  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7998                         GPR32, VectorIndexB>;
7999  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
8000                         GPR32, VectorIndexH>;
8001  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
8002                         GPR32, VectorIndexS>;
8003  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
8004                         GPR64, VectorIndexD>;
8005
8006  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
8007                         VectorIndexB>;
8008  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
8009                         VectorIndexH>;
8010  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
8011                         VectorIndexS>;
8012  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
8013                         VectorIndexD>;
8014}
8015
8016//----------------------------------------------------------------------------
8017// AdvSIMD TBL/TBX
8018//----------------------------------------------------------------------------
8019
8020let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8021class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8022                          RegisterOperand listtype, string asm, string kind>
8023  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
8024       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
8025    Sched<[!if(Q, WriteVq, WriteVd)]> {
8026  bits<5> Vd;
8027  bits<5> Vn;
8028  bits<5> Vm;
8029  let Inst{31}    = 0;
8030  let Inst{30}    = Q;
8031  let Inst{29-21} = 0b001110000;
8032  let Inst{20-16} = Vm;
8033  let Inst{15}    = 0;
8034  let Inst{14-13} = len;
8035  let Inst{12}    = op;
8036  let Inst{11-10} = 0b00;
8037  let Inst{9-5}   = Vn;
8038  let Inst{4-0}   = Vd;
8039}
8040
8041let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8042class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8043                          RegisterOperand listtype, string asm, string kind>
8044  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
8045       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
8046    Sched<[!if(Q, WriteVq, WriteVd)]> {
8047  bits<5> Vd;
8048  bits<5> Vn;
8049  bits<5> Vm;
8050  let Inst{31}    = 0;
8051  let Inst{30}    = Q;
8052  let Inst{29-21} = 0b001110000;
8053  let Inst{20-16} = Vm;
8054  let Inst{15}    = 0;
8055  let Inst{14-13} = len;
8056  let Inst{12}    = op;
8057  let Inst{11-10} = 0b00;
8058  let Inst{9-5}   = Vn;
8059  let Inst{4-0}   = Vd;
8060}
8061
8062class SIMDTableLookupAlias<string asm, Instruction inst,
8063                          RegisterOperand vectype, RegisterOperand listtype>
8064    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
8065                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
8066
8067multiclass SIMDTableLookup<bit op, string asm> {
8068  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
8069                                      asm, ".8b">;
8070  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
8071                                      asm, ".8b">;
8072  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
8073                                      asm, ".8b">;
8074  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
8075                                      asm, ".8b">;
8076  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
8077                                      asm, ".16b">;
8078  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
8079                                      asm, ".16b">;
8080  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
8081                                      asm, ".16b">;
8082  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
8083                                      asm, ".16b">;
8084
8085  def : SIMDTableLookupAlias<asm # ".8b",
8086                         !cast<Instruction>(NAME#"v8i8One"),
8087                         V64, VecListOne128>;
8088  def : SIMDTableLookupAlias<asm # ".8b",
8089                         !cast<Instruction>(NAME#"v8i8Two"),
8090                         V64, VecListTwo128>;
8091  def : SIMDTableLookupAlias<asm # ".8b",
8092                         !cast<Instruction>(NAME#"v8i8Three"),
8093                         V64, VecListThree128>;
8094  def : SIMDTableLookupAlias<asm # ".8b",
8095                         !cast<Instruction>(NAME#"v8i8Four"),
8096                         V64, VecListFour128>;
8097  def : SIMDTableLookupAlias<asm # ".16b",
8098                         !cast<Instruction>(NAME#"v16i8One"),
8099                         V128, VecListOne128>;
8100  def : SIMDTableLookupAlias<asm # ".16b",
8101                         !cast<Instruction>(NAME#"v16i8Two"),
8102                         V128, VecListTwo128>;
8103  def : SIMDTableLookupAlias<asm # ".16b",
8104                         !cast<Instruction>(NAME#"v16i8Three"),
8105                         V128, VecListThree128>;
8106  def : SIMDTableLookupAlias<asm # ".16b",
8107                         !cast<Instruction>(NAME#"v16i8Four"),
8108                         V128, VecListFour128>;
8109}
8110
8111multiclass SIMDTableLookupTied<bit op, string asm> {
8112  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
8113                                      asm, ".8b">;
8114  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
8115                                      asm, ".8b">;
8116  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
8117                                      asm, ".8b">;
8118  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
8119                                      asm, ".8b">;
8120  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
8121                                      asm, ".16b">;
8122  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
8123                                      asm, ".16b">;
8124  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
8125                                      asm, ".16b">;
8126  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
8127                                      asm, ".16b">;
8128
8129  def : SIMDTableLookupAlias<asm # ".8b",
8130                         !cast<Instruction>(NAME#"v8i8One"),
8131                         V64, VecListOne128>;
8132  def : SIMDTableLookupAlias<asm # ".8b",
8133                         !cast<Instruction>(NAME#"v8i8Two"),
8134                         V64, VecListTwo128>;
8135  def : SIMDTableLookupAlias<asm # ".8b",
8136                         !cast<Instruction>(NAME#"v8i8Three"),
8137                         V64, VecListThree128>;
8138  def : SIMDTableLookupAlias<asm # ".8b",
8139                         !cast<Instruction>(NAME#"v8i8Four"),
8140                         V64, VecListFour128>;
8141  def : SIMDTableLookupAlias<asm # ".16b",
8142                         !cast<Instruction>(NAME#"v16i8One"),
8143                         V128, VecListOne128>;
8144  def : SIMDTableLookupAlias<asm # ".16b",
8145                         !cast<Instruction>(NAME#"v16i8Two"),
8146                         V128, VecListTwo128>;
8147  def : SIMDTableLookupAlias<asm # ".16b",
8148                         !cast<Instruction>(NAME#"v16i8Three"),
8149                         V128, VecListThree128>;
8150  def : SIMDTableLookupAlias<asm # ".16b",
8151                         !cast<Instruction>(NAME#"v16i8Four"),
8152                         V128, VecListFour128>;
8153}
8154
8155//----------------------------------------------------------------------------
8156// AdvSIMD LUT
8157//----------------------------------------------------------------------------
8158let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8159class BaseSIMDTableLookupIndexed<bit Q, bits<5> opc, RegisterOperand vectype,
8160                            RegisterOperand listtype, Operand idx_type,
8161                            string asm, string kind>
8162  : I<(outs vectype:$Rd),
8163      (ins listtype:$Rn, vectype:$Rm, idx_type:$idx),
8164      asm, "\t$Rd" # kind # ", $Rn, $Rm$idx", "", []>,
8165    Sched<[]> {
8166  bits<5> Rd;
8167  bits<5> Rn;
8168  bits<5> Rm;
8169  let Inst{31}    = 0;
8170  let Inst{30}    = Q;
8171  let Inst{29-24} = 0b001110;
8172  let Inst{23-22} = opc{4-3};
8173  let Inst{21}    = 0;
8174  let Inst{20-16} = Rm;
8175  let Inst{15}    = 0;
8176  let Inst{14-12} = opc{2-0};
8177  let Inst{11-10} = 0b00;
8178  let Inst{9-5}   = Rn;
8179  let Inst{4-0}   = Rd;
8180}
8181
8182multiclass BaseSIMDTableLookupIndexed2<string asm> {
8183  def v16f8 : BaseSIMDTableLookupIndexed<0b1, {0b10,?,?,0b1}, V128, VecListOne16b, VectorIndexS, asm, ".16b"> {
8184    bits<2> idx;
8185    let Inst{14-13} = idx;
8186  }
8187  def v8f16 : BaseSIMDTableLookupIndexed<0b1, {0b11,?,?,?}, V128, VecListOne8h, VectorIndexH, asm, ".8h" > {
8188    bits<3> idx;
8189    let Inst{14-12} = idx;
8190  }
8191}
8192
8193multiclass BaseSIMDTableLookupIndexed4<string asm> {
8194  def v16f8 : BaseSIMDTableLookupIndexed<0b1, {0b01,?,0b10}, V128, VecListOne16b, VectorIndexD, asm, ".16b"> {
8195    bit idx;
8196    let Inst{14} = idx;
8197  }
8198  def v8f16 : BaseSIMDTableLookupIndexed<0b1, {0b01,?,?,0b1}, V128, VecListTwo8h, VectorIndexS, asm, ".8h" > {
8199    bits<2> idx;
8200    let Inst{14-13} = idx;
8201  }
8202}
8203
8204//----------------------------------------------------------------------------
8205// AdvSIMD scalar DUP
8206//----------------------------------------------------------------------------
8207let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8208class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
8209                        string asm, string kind, Operand idxtype>
8210  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
8211       "{\t$dst, $src" # kind # "$idx" #
8212       "|\t$dst, $src$idx}", "", []>,
8213    Sched<[WriteVd]> {
8214  bits<5> dst;
8215  bits<5> src;
8216  let Inst{31-21} = 0b01011110000;
8217  let Inst{15-10} = 0b000001;
8218  let Inst{9-5}   = src;
8219  let Inst{4-0}   = dst;
8220}
8221
8222class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
8223      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
8224    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
8225                    # "|\t$dst, $src$index}",
8226                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
8227
8228
8229multiclass SIMDScalarDUP<string asm> {
8230  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
8231    bits<4> idx;
8232    let Inst{20-17} = idx;
8233    let Inst{16} = 1;
8234  }
8235  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
8236    bits<3> idx;
8237    let Inst{20-18} = idx;
8238    let Inst{17-16} = 0b10;
8239  }
8240  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
8241    bits<2> idx;
8242    let Inst{20-19} = idx;
8243    let Inst{18-16} = 0b100;
8244  }
8245  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
8246    bits<1> idx;
8247    let Inst{20} = idx;
8248    let Inst{19-16} = 0b1000;
8249  }
8250
8251  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
8252                                                          VectorIndexD:$idx)))),
8253            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
8254
8255  // 'DUP' mnemonic aliases.
8256  def : SIMDScalarDUPAlias<"dup", ".b",
8257                           !cast<Instruction>(NAME#"i8"),
8258                           FPR8, V128, VectorIndexB>;
8259  def : SIMDScalarDUPAlias<"dup", ".h",
8260                           !cast<Instruction>(NAME#"i16"),
8261                           FPR16, V128, VectorIndexH>;
8262  def : SIMDScalarDUPAlias<"dup", ".s",
8263                           !cast<Instruction>(NAME#"i32"),
8264                           FPR32, V128, VectorIndexS>;
8265  def : SIMDScalarDUPAlias<"dup", ".d",
8266                           !cast<Instruction>(NAME#"i64"),
8267                           FPR64, V128, VectorIndexD>;
8268}
8269
8270//----------------------------------------------------------------------------
8271// AdvSIMD modified immediate instructions
8272//----------------------------------------------------------------------------
8273
8274class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
8275                          string asm, string op_string,
8276                          string cstr, list<dag> pattern>
8277  : I<oops, iops, asm, op_string, cstr, pattern>,
8278    Sched<[!if(Q, WriteVq, WriteVd)]> {
8279  bits<5> Rd;
8280  bits<8> imm8;
8281  let Inst{31}    = 0;
8282  let Inst{30}    = Q;
8283  let Inst{29}    = op;
8284  let Inst{28-19} = 0b0111100000;
8285  let Inst{18-16} = imm8{7-5};
8286  let Inst{11} = op2;
8287  let Inst{10} = 1;
8288  let Inst{9-5}   = imm8{4-0};
8289  let Inst{4-0}   = Rd;
8290}
8291
8292class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
8293                                Operand immtype, dag opt_shift_iop,
8294                                string opt_shift, string asm, string kind,
8295                                list<dag> pattern>
8296  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
8297                        !con((ins immtype:$imm8), opt_shift_iop), asm,
8298                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
8299                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8300                        "", pattern> {
8301  let DecoderMethod = "DecodeModImmInstruction";
8302}
8303
8304class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
8305                                Operand immtype, dag opt_shift_iop,
8306                                string opt_shift, string asm, string kind,
8307                                list<dag> pattern>
8308  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
8309                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
8310                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
8311                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8312                        "$Rd = $dst", pattern> {
8313  let DecoderMethod = "DecodeModImmTiedInstruction";
8314}
8315
8316class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
8317                                     RegisterOperand vectype, string asm,
8318                                     string kind, list<dag> pattern>
8319  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8320                              (ins logical_vec_shift:$shift),
8321                              "$shift", asm, kind, pattern> {
8322  bits<2> shift;
8323  let Inst{15}    = b15_b12{1};
8324  let Inst{14-13} = shift;
8325  let Inst{12}    = b15_b12{0};
8326}
8327
8328class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
8329                                     RegisterOperand vectype, string asm,
8330                                     string kind, list<dag> pattern>
8331  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8332                              (ins logical_vec_shift:$shift),
8333                              "$shift", asm, kind, pattern> {
8334  bits<2> shift;
8335  let Inst{15}    = b15_b12{1};
8336  let Inst{14-13} = shift;
8337  let Inst{12}    = b15_b12{0};
8338}
8339
8340
8341class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
8342                                         RegisterOperand vectype, string asm,
8343                                         string kind, list<dag> pattern>
8344  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8345                              (ins logical_vec_hw_shift:$shift),
8346                              "$shift", asm, kind, pattern> {
8347  bits<2> shift;
8348  let Inst{15} = b15_b12{1};
8349  let Inst{14} = 0;
8350  let Inst{13} = shift{0};
8351  let Inst{12} = b15_b12{0};
8352}
8353
8354class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
8355                                         RegisterOperand vectype, string asm,
8356                                         string kind, list<dag> pattern>
8357  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8358                              (ins logical_vec_hw_shift:$shift),
8359                              "$shift", asm, kind, pattern> {
8360  bits<2> shift;
8361  let Inst{15} = b15_b12{1};
8362  let Inst{14} = 0;
8363  let Inst{13} = shift{0};
8364  let Inst{12} = b15_b12{0};
8365}
8366
8367multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
8368                                      string asm> {
8369  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
8370                                                 asm, ".4h", []>;
8371  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
8372                                                 asm, ".8h", []>;
8373
8374  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
8375                                             asm, ".2s", []>;
8376  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
8377                                             asm, ".4s", []>;
8378}
8379
8380multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
8381                                      bits<2> w_cmode, string asm,
8382                                      SDNode OpNode> {
8383  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
8384                                                 asm, ".4h",
8385             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
8386                                             imm0_255:$imm8,
8387                                             (i32 imm:$shift)))]>;
8388  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
8389                                                 asm, ".8h",
8390             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
8391                                              imm0_255:$imm8,
8392                                              (i32 imm:$shift)))]>;
8393
8394  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
8395                                             asm, ".2s",
8396             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
8397                                             imm0_255:$imm8,
8398                                             (i32 imm:$shift)))]>;
8399  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
8400                                             asm, ".4s",
8401             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
8402                                              imm0_255:$imm8,
8403                                              (i32 imm:$shift)))]>;
8404}
8405
8406class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
8407                             RegisterOperand vectype, string asm,
8408                             string kind, list<dag> pattern>
8409  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8410                              (ins move_vec_shift:$shift),
8411                              "$shift", asm, kind, pattern> {
8412  bits<1> shift;
8413  let Inst{15-13} = cmode{3-1};
8414  let Inst{12}    = shift;
8415}
8416
8417class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
8418                                   RegisterOperand vectype,
8419                                   Operand imm_type, string asm,
8420                                   string kind, list<dag> pattern>
8421  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
8422                              asm, kind, pattern> {
8423  let Inst{15-12} = cmode;
8424}
8425
8426class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
8427                                   list<dag> pattern>
8428  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
8429                        "\t$Rd, $imm8", "", pattern> {
8430  let Inst{15-12} = cmode;
8431  let DecoderMethod = "DecodeModImmInstruction";
8432}
8433
8434//----------------------------------------------------------------------------
8435// AdvSIMD indexed element
8436//----------------------------------------------------------------------------
8437
8438let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8439class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8440                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8441                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8442                      string apple_kind, string dst_kind, string lhs_kind,
8443                      string rhs_kind, list<dag> pattern>
8444  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8445      asm,
8446      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8447      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8448    Sched<[WriteVd]> {
8449  bits<5> Rd;
8450  bits<5> Rn;
8451  bits<5> Rm;
8452
8453  let Inst{31}    = 0;
8454  let Inst{30}    = Q;
8455  let Inst{29}    = U;
8456  let Inst{28}    = Scalar;
8457  let Inst{27-24} = 0b1111;
8458  let Inst{23-22} = size;
8459  // Bit 21 must be set by the derived class.
8460  let Inst{20-16} = Rm;
8461  let Inst{15-12} = opc;
8462  // Bit 11 must be set by the derived class.
8463  let Inst{10}    = 0;
8464  let Inst{9-5}   = Rn;
8465  let Inst{4-0}   = Rd;
8466}
8467
8468let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8469class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8470                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8471                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8472                      string apple_kind, string dst_kind, string lhs_kind,
8473                      string rhs_kind, list<dag> pattern>
8474  : I<(outs dst_reg:$dst),
8475      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8476      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8477      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8478    Sched<[WriteVd]> {
8479  bits<5> Rd;
8480  bits<5> Rn;
8481  bits<5> Rm;
8482
8483  let Inst{31}    = 0;
8484  let Inst{30}    = Q;
8485  let Inst{29}    = U;
8486  let Inst{28}    = Scalar;
8487  let Inst{27-24} = 0b1111;
8488  let Inst{23-22} = size;
8489  // Bit 21 must be set by the derived class.
8490  let Inst{20-16} = Rm;
8491  let Inst{15-12} = opc;
8492  // Bit 11 must be set by the derived class.
8493  let Inst{10}    = 0;
8494  let Inst{9-5}   = Rn;
8495  let Inst{4-0}   = Rd;
8496}
8497
8498
8499//----------------------------------------------------------------------------
8500// Armv8.6 BFloat16 Extension
8501//----------------------------------------------------------------------------
8502let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8503
8504class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8505                                   string kind2, RegisterOperand RegType,
8506                                   ValueType AccumType, ValueType InputType>
8507  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8508                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8509                                            (InputType RegType:$Rn),
8510                                            (InputType RegType:$Rm)))]> {
8511  let AsmString = !strconcat(asm,
8512                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8513                               ", $Rm" # kind2 # "}");
8514}
8515
8516multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8517  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8518                                           v2f32, v4bf16>;
8519  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8520                                           v4f32, v8bf16>;
8521}
8522
8523class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8524                                      string dst_kind, string lhs_kind,
8525                                      string rhs_kind,
8526                                      RegisterOperand RegType,
8527                                      ValueType AccumType,
8528                                      ValueType InputType>
8529  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8530                        RegType, RegType, V128, VectorIndexS,
8531                        asm, "", dst_kind, lhs_kind, rhs_kind,
8532        [(set (AccumType RegType:$dst),
8533              (AccumType (int_aarch64_neon_bfdot
8534                                 (AccumType RegType:$Rd),
8535                                 (InputType RegType:$Rn),
8536                                 (InputType (bitconvert (AccumType
8537                                    (AArch64duplane32 (v4f32 V128:$Rm),
8538                                        VectorIndexS:$idx)))))))]> {
8539
8540  bits<2> idx;
8541  let Inst{21}    = idx{0};  // L
8542  let Inst{11}    = idx{1};  // H
8543}
8544
8545multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8546
8547  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8548                                               ".2h", V64, v2f32, v4bf16>;
8549  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8550                                              ".2h", V128, v4f32, v8bf16>;
8551}
8552
8553let mayRaiseFPException = 1, Uses = [FPCR] in
8554class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8555  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8556              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8557                                               (v8bf16 V128:$Rn),
8558                                               (v8bf16 V128:$Rm)))]> {
8559  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8560}
8561
8562let mayRaiseFPException = 1, Uses = [FPCR] in
8563class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8564  : I<(outs V128:$dst),
8565      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8566      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8567          [(set (v4f32 V128:$dst),
8568                (v4f32 (OpNode (v4f32 V128:$Rd),
8569                               (v8bf16 V128:$Rn),
8570                               (v8bf16
8571                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8572                                      VectorIndexH:$idx)))))]>,
8573    Sched<[WriteVq]> {
8574  bits<5> Rd;
8575  bits<5> Rn;
8576  bits<4> Rm;
8577  bits<3> idx;
8578
8579  let Inst{31}    = 0;
8580  let Inst{30}    = Q;
8581  let Inst{29-22} = 0b00111111;
8582  let Inst{21-20} = idx{1-0};
8583  let Inst{19-16} = Rm;
8584  let Inst{15-12} = 0b1111;
8585  let Inst{11}    = idx{2};   // H
8586  let Inst{10}    = 0;
8587  let Inst{9-5}   = Rn;
8588  let Inst{4-0}   = Rd;
8589}
8590
8591class SIMDThreeSameVectorBF16MatrixMul<string asm>
8592  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8593                                V128, asm, ".4s",
8594                          [(set (v4f32 V128:$dst),
8595                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8596                                                         (v8bf16 V128:$Rn),
8597                                                         (v8bf16 V128:$Rm)))]> {
8598  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8599                                    ", $Rm", ".8h", "}");
8600}
8601
8602let mayRaiseFPException = 1, Uses = [FPCR] in
8603class SIMD_BFCVTN
8604  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8605                           "bfcvtn", ".4h", ".4s",
8606    [(set (v8bf16 V128:$Rd),
8607          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8608
8609let mayRaiseFPException = 1, Uses = [FPCR] in
8610class SIMD_BFCVTN2
8611  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8612                           "bfcvtn2", ".8h", ".4s",
8613    [(set (v8bf16 V128:$dst),
8614          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8615
8616let mayRaiseFPException = 1, Uses = [FPCR] in
8617class BF16ToSinglePrecision<string asm>
8618  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8619    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8620    Sched<[WriteFCvt]> {
8621  bits<5> Rd;
8622  bits<5> Rn;
8623  let Inst{31-10} = 0b0001111001100011010000;
8624  let Inst{9-5}   = Rn;
8625  let Inst{4-0}   = Rd;
8626}
8627} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8628
8629//----------------------------------------------------------------------------
8630class BaseSIMDThreeSameVectorIndexB<bit Q, bit U, bits<2> sz, bits<4> opc,
8631                                    string asm, string dst_kind,
8632                                    RegisterOperand RegType,
8633                                    RegisterOperand RegType_lo>
8634  : BaseSIMDIndexedTied<Q, U, 0b0, sz, opc,
8635                        RegType, RegType, RegType_lo, VectorIndexB,
8636                        asm, "", dst_kind, ".16b", ".b", []> {
8637
8638  // idx = H:L:M
8639  bits<4> idx;
8640  let Inst{11}    = idx{3};
8641  let Inst{21-19} = idx{2-0};
8642}
8643
8644multiclass SIMDThreeSameVectorMLAIndex<bit Q, string asm> {
8645  def v8f16 : BaseSIMDThreeSameVectorIndexB<Q, 0b0, 0b11, 0b0000, asm, ".8h",
8646                                            V128, V128_0to7>;
8647}
8648
8649multiclass SIMDThreeSameVectorMLALIndex<bit Q, bits<2> sz, string asm> {
8650  def v4f32 : BaseSIMDThreeSameVectorIndexB<Q, 0b1, sz, 0b1000, asm, ".4s",
8651                                            V128, V128_0to7>;
8652}
8653
8654//----------------------------------------------------------------------------
8655// Armv8.6 Matrix Multiply Extension
8656//----------------------------------------------------------------------------
8657
8658class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8659  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8660              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8661                                               (v16i8 V128:$Rn),
8662                                               (v16i8 V128:$Rm)))]> {
8663  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8664}
8665
8666//----------------------------------------------------------------------------
8667// ARMv8.2-A Dot Product Instructions (Indexed)
8668class BaseSIMDThreeSameVectorIndexS<bit Q, bit U, bits<2> size, bits<4> opc, string asm,
8669                                    string dst_kind, string lhs_kind, string rhs_kind,
8670                                    RegisterOperand RegType,
8671                                    ValueType AccumType, ValueType InputType,
8672                                    SDPatternOperator OpNode> :
8673        BaseSIMDIndexedTied<Q, U, 0b0, size, opc, RegType, RegType, V128,
8674                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8675        [(set (AccumType RegType:$dst),
8676              (AccumType (OpNode (AccumType RegType:$Rd),
8677                                 (InputType RegType:$Rn),
8678                                 (InputType (bitconvert (AccumType
8679                                    (AArch64duplane32 (v4i32 V128:$Rm),
8680                                        VectorIndexS:$idx)))))))]> {
8681  bits<2> idx;
8682  let Inst{21}    = idx{0};  // L
8683  let Inst{11}    = idx{1};  // H
8684}
8685
8686multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8687                                       SDPatternOperator OpNode> {
8688  def v8i8  : BaseSIMDThreeSameVectorIndexS<0, U, size, {0b111, Mixed}, asm, ".2s", ".8b", ".4b",
8689                                              V64, v2i32, v8i8, OpNode>;
8690  def v16i8 : BaseSIMDThreeSameVectorIndexS<1, U, size, {0b111, Mixed}, asm, ".4s", ".16b", ".4b",
8691                                              V128, v4i32, v16i8, OpNode>;
8692}
8693
8694// TODO: The vectors v8i8 and v16i8 should be v8f8 and v16f8
8695multiclass SIMDThreeSameVectorFP8DOT4Index<string asm> {
8696  def v8f8 : BaseSIMDThreeSameVectorIndexS<0b0, 0b0, 0b00, 0b0000, asm, ".2s", ".8b", ".4b",
8697                                           V64, v2f32, v8i8, null_frag>;
8698  def v16f8 : BaseSIMDThreeSameVectorIndexS<0b1, 0b0, 0b00, 0b0000, asm, ".4s", ".16b",".4b",
8699                                            V128, v4f32, v16i8, null_frag>;
8700}
8701
8702// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8703let mayRaiseFPException = 1, Uses = [FPCR] in
8704class BaseSIMDThreeSameVectorIndexH<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
8705                                      string dst_kind, string lhs_kind,
8706                                      string rhs_kind, RegisterOperand RegType,
8707                                      RegisterOperand RegType_lo, ValueType AccumType,
8708                                      ValueType InputType, SDPatternOperator OpNode> :
8709        BaseSIMDIndexedTied<Q, U, 0, sz, opc, RegType, RegType, RegType_lo,
8710                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8711          [(set (AccumType RegType:$dst),
8712                (AccumType (OpNode (AccumType RegType:$Rd),
8713                                   (InputType RegType:$Rn),
8714                                   (InputType (AArch64duplane16 (v8f16 V128_lo:$Rm),
8715                                                VectorIndexH:$idx)))))]> {
8716  // idx = H:L:M
8717  bits<3> idx;
8718  let Inst{11} = idx{2}; // H
8719  let Inst{21} = idx{1}; // L
8720  let Inst{20} = idx{0}; // M
8721}
8722
8723multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8724                                       SDPatternOperator OpNode> {
8725  def v4f16 : BaseSIMDThreeSameVectorIndexH<0, U, 0b10, opc, asm, ".2s", ".2h", ".h",
8726                                              V64, V128_lo, v2f32, v4f16, OpNode>;
8727  def v8f16 : BaseSIMDThreeSameVectorIndexH<1, U, 0b10, opc, asm, ".4s", ".4h", ".h",
8728                                              V128, V128_lo, v4f32, v8f16, OpNode>;
8729}
8730
8731//----------------------------------------------------------------------------
8732// FP8 Advanced SIMD vector x indexed element
8733// TODO: Replace value types v8i8 and v16i8 by v8f8 and v16f8
8734multiclass SIMDThreeSameVectorFP8DOT2Index<string asm> {
8735  def v4f16 : BaseSIMDThreeSameVectorIndexH<0b0, 0b0, 0b01, 0b0000, asm, ".4h", ".8b", ".2b",
8736                                            V64, V128_lo, v4f16, v8i8, null_frag>;
8737  def v8f16 : BaseSIMDThreeSameVectorIndexH<0b1, 0b0, 0b01, 0b0000, asm, ".8h", ".16b", ".2b",
8738                                            V128, V128_lo, v8f16, v8i16, null_frag>;
8739}
8740
8741multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8742                         SDPatternOperator OpNode> {
8743  let mayRaiseFPException = 1, Uses = [FPCR] in {
8744  let Predicates = [HasNEON, HasFullFP16] in {
8745  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8746                                      V64, V64,
8747                                      V128_lo, VectorIndexH,
8748                                      asm, ".4h", ".4h", ".4h", ".h",
8749    [(set (v4f16 V64:$Rd),
8750        (OpNode (v4f16 V64:$Rn),
8751         (dup_v8f16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8752    bits<3> idx;
8753    let Inst{11} = idx{2};
8754    let Inst{21} = idx{1};
8755    let Inst{20} = idx{0};
8756  }
8757
8758  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8759                                      V128, V128,
8760                                      V128_lo, VectorIndexH,
8761                                      asm, ".8h", ".8h", ".8h", ".h",
8762    [(set (v8f16 V128:$Rd),
8763        (OpNode (v8f16 V128:$Rn),
8764         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8765    bits<3> idx;
8766    let Inst{11} = idx{2};
8767    let Inst{21} = idx{1};
8768    let Inst{20} = idx{0};
8769  }
8770  } // Predicates = [HasNEON, HasFullFP16]
8771
8772  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8773                                      V64, V64,
8774                                      V128, VectorIndexS,
8775                                      asm, ".2s", ".2s", ".2s", ".s",
8776    [(set (v2f32 V64:$Rd),
8777        (OpNode (v2f32 V64:$Rn),
8778         (dup_v4f32 (v4f32 V128:$Rm), VectorIndexS:$idx)))]> {
8779    bits<2> idx;
8780    let Inst{11} = idx{1};
8781    let Inst{21} = idx{0};
8782  }
8783
8784  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8785                                      V128, V128,
8786                                      V128, VectorIndexS,
8787                                      asm, ".4s", ".4s", ".4s", ".s",
8788    [(set (v4f32 V128:$Rd),
8789        (OpNode (v4f32 V128:$Rn),
8790         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8791    bits<2> idx;
8792    let Inst{11} = idx{1};
8793    let Inst{21} = idx{0};
8794  }
8795
8796  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8797                                      V128, V128,
8798                                      V128, VectorIndexD,
8799                                      asm, ".2d", ".2d", ".2d", ".d",
8800    [(set (v2f64 V128:$Rd),
8801        (OpNode (v2f64 V128:$Rn),
8802         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8803    bits<1> idx;
8804    let Inst{11} = idx{0};
8805    let Inst{21} = 0;
8806  }
8807
8808  let Predicates = [HasNEON, HasFullFP16] in {
8809  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8810                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8811                                      asm, ".h", "", "", ".h",
8812    [(set (f16 FPR16Op:$Rd),
8813          (OpNode (f16 FPR16Op:$Rn),
8814                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8815                                       VectorIndexH:$idx))))]> {
8816    bits<3> idx;
8817    let Inst{11} = idx{2};
8818    let Inst{21} = idx{1};
8819    let Inst{20} = idx{0};
8820  }
8821  } // Predicates = [HasNEON, HasFullFP16]
8822
8823  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8824                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8825                                      asm, ".s", "", "", ".s",
8826    [(set (f32 FPR32Op:$Rd),
8827          (OpNode (f32 FPR32Op:$Rn),
8828                  (f32 (vector_extract (v4f32 V128:$Rm),
8829                                       VectorIndexS:$idx))))]> {
8830    bits<2> idx;
8831    let Inst{11} = idx{1};
8832    let Inst{21} = idx{0};
8833  }
8834
8835  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8836                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8837                                      asm, ".d", "", "", ".d",
8838    [(set (f64 FPR64Op:$Rd),
8839          (OpNode (f64 FPR64Op:$Rn),
8840                  (f64 (vector_extract (v2f64 V128:$Rm),
8841                                       VectorIndexD:$idx))))]> {
8842    bits<1> idx;
8843    let Inst{11} = idx{0};
8844    let Inst{21} = 0;
8845  }
8846  } // mayRaiseFPException = 1, Uses = [FPCR]
8847
8848  let Predicates = [HasNEON, HasFullFP16] in {
8849  def : Pat<(f16 (OpNode
8850                   (f16 (vector_extract (v8f16 V128:$Rn), (i64 0))),
8851                   (f16 (vector_extract (v8f16 V128:$Rm), VectorIndexH:$idx)))),
8852            (!cast<Instruction>(NAME # v1i16_indexed)
8853              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), V128:$Rm, VectorIndexH:$idx)>;
8854  }
8855
8856  let Predicates = [HasNEON] in {
8857  def : Pat<(f32 (OpNode
8858                   (f32 (vector_extract (v4f32 V128:$Rn), (i64 0))),
8859                   (f32 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx)))),
8860            (!cast<Instruction>(NAME # v1i32_indexed)
8861              (EXTRACT_SUBREG V128:$Rn, ssub), V128:$Rm, VectorIndexS:$idx)>;
8862
8863  def : Pat<(f64 (OpNode
8864                   (f64 (vector_extract (v2f64 V128:$Rn), (i64 0))),
8865                   (f64 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx)))),
8866            (!cast<Instruction>(NAME # v1i64_indexed)
8867              (EXTRACT_SUBREG V128:$Rn, dsub), V128:$Rm, VectorIndexD:$idx)>;
8868  }
8869}
8870
8871multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8872  let Predicates = [HasNEON, HasFullFP16] in {
8873  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8874  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8875                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8876                                           VectorIndexH:$idx))),
8877            (!cast<Instruction>(INST # "v8i16_indexed")
8878                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8879  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8880                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8881            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8882                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8883
8884  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8885                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8886                                           VectorIndexH:$idx))),
8887            (!cast<Instruction>(INST # "v4i16_indexed")
8888                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8889  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8890                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8891            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8892                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8893
8894  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8895                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8896            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8897                V128_lo:$Rm, VectorIndexH:$idx)>;
8898  } // Predicates = [HasNEON, HasFullFP16]
8899
8900  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8901  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8902                           (AArch64duplane32 (v4f32 V128:$Rm),
8903                                           VectorIndexS:$idx))),
8904            (!cast<Instruction>(INST # v2i32_indexed)
8905                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8906  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8907                           (AArch64dup (f32 FPR32Op:$Rm)))),
8908            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8909                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8910
8911
8912  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8913  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8914                           (AArch64duplane32 (v4f32 V128:$Rm),
8915                                           VectorIndexS:$idx))),
8916            (!cast<Instruction>(INST # "v4i32_indexed")
8917                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8918  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8919                           (AArch64dup (f32 FPR32Op:$Rm)))),
8920            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8921                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8922
8923  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8924  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8925                           (AArch64duplane64 (v2f64 V128:$Rm),
8926                                           VectorIndexD:$idx))),
8927            (!cast<Instruction>(INST # "v2i64_indexed")
8928                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8929  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8930                           (AArch64dup (f64 FPR64Op:$Rm)))),
8931            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8932                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8933
8934  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8935  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8936                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8937            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8938                V128:$Rm, VectorIndexS:$idx)>;
8939
8940  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8941  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8942                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8943            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8944                V128:$Rm, VectorIndexD:$idx)>;
8945}
8946
8947let mayRaiseFPException = 1, Uses = [FPCR] in
8948multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8949  let Predicates = [HasNEON, HasFullFP16] in {
8950  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8951                                          V128_lo, VectorIndexH,
8952                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8953    bits<3> idx;
8954    let Inst{11} = idx{2};
8955    let Inst{21} = idx{1};
8956    let Inst{20} = idx{0};
8957  }
8958
8959  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8960                                          V128, V128,
8961                                          V128_lo, VectorIndexH,
8962                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8963    bits<3> idx;
8964    let Inst{11} = idx{2};
8965    let Inst{21} = idx{1};
8966    let Inst{20} = idx{0};
8967  }
8968  } // Predicates = [HasNEON, HasFullFP16]
8969
8970  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8971                                          V128, VectorIndexS,
8972                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8973    bits<2> idx;
8974    let Inst{11} = idx{1};
8975    let Inst{21} = idx{0};
8976  }
8977
8978  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8979                                      V128, V128,
8980                                      V128, VectorIndexS,
8981                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8982    bits<2> idx;
8983    let Inst{11} = idx{1};
8984    let Inst{21} = idx{0};
8985  }
8986
8987  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8988                                      V128, V128,
8989                                      V128, VectorIndexD,
8990                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8991    bits<1> idx;
8992    let Inst{11} = idx{0};
8993    let Inst{21} = 0;
8994  }
8995
8996  let Predicates = [HasNEON, HasFullFP16] in {
8997  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8998                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8999                                      asm, ".h", "", "", ".h", []> {
9000    bits<3> idx;
9001    let Inst{11} = idx{2};
9002    let Inst{21} = idx{1};
9003    let Inst{20} = idx{0};
9004  }
9005  } // Predicates = [HasNEON, HasFullFP16]
9006
9007  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9008                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9009                                      asm, ".s", "", "", ".s", []> {
9010    bits<2> idx;
9011    let Inst{11} = idx{1};
9012    let Inst{21} = idx{0};
9013  }
9014
9015  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
9016                                      FPR64Op, FPR64Op, V128, VectorIndexD,
9017                                      asm, ".d", "", "", ".d", []> {
9018    bits<1> idx;
9019    let Inst{11} = idx{0};
9020    let Inst{21} = 0;
9021  }
9022}
9023
9024multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
9025                                 SDPatternOperator OpNodeLaneQ> {
9026
9027  def : Pat<(v4i16 (OpNodeLane
9028                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
9029                     VectorIndexS32b:$idx)),
9030            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
9031              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
9032              (UImmS1XForm $idx))>;
9033
9034  def : Pat<(v4i16 (OpNodeLaneQ
9035                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
9036                     VectorIndexH32b:$idx)),
9037            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
9038              (UImmS1XForm $idx))>;
9039
9040  def : Pat<(v8i16 (OpNodeLane
9041                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
9042                     VectorIndexS32b:$idx)),
9043            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
9044              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9045              (UImmS1XForm $idx))>;
9046
9047  def : Pat<(v8i16 (OpNodeLaneQ
9048                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
9049                     VectorIndexH32b:$idx)),
9050            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
9051              (UImmS1XForm $idx))>;
9052
9053  def : Pat<(v2i32 (OpNodeLane
9054                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
9055                     VectorIndexD32b:$idx)),
9056            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
9057              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
9058              (UImmS1XForm $idx))>;
9059
9060  def : Pat<(v2i32 (OpNodeLaneQ
9061                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
9062                     VectorIndexS32b:$idx)),
9063            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
9064              (UImmS1XForm $idx))>;
9065
9066  def : Pat<(v4i32 (OpNodeLane
9067                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
9068                     VectorIndexD32b:$idx)),
9069            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
9070              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9071              (UImmS1XForm $idx))>;
9072
9073  def : Pat<(v4i32 (OpNodeLaneQ
9074                     (v4i32 V128:$Rn),
9075                     (v4i32 V128:$Rm),
9076                     VectorIndexS32b:$idx)),
9077            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
9078              (UImmS1XForm $idx))>;
9079
9080}
9081
9082multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
9083                         SDPatternOperator OpNode> {
9084  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
9085                                      V128_lo, VectorIndexH,
9086                                      asm, ".4h", ".4h", ".4h", ".h",
9087    [(set (v4i16 V64:$Rd),
9088        (OpNode (v4i16 V64:$Rn),
9089         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9090    bits<3> idx;
9091    let Inst{11} = idx{2};
9092    let Inst{21} = idx{1};
9093    let Inst{20} = idx{0};
9094  }
9095
9096  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9097                                      V128, V128,
9098                                      V128_lo, VectorIndexH,
9099                                      asm, ".8h", ".8h", ".8h", ".h",
9100    [(set (v8i16 V128:$Rd),
9101       (OpNode (v8i16 V128:$Rn),
9102         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9103    bits<3> idx;
9104    let Inst{11} = idx{2};
9105    let Inst{21} = idx{1};
9106    let Inst{20} = idx{0};
9107  }
9108
9109  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9110                                      V64, V64,
9111                                      V128, VectorIndexS,
9112                                      asm, ".2s", ".2s", ".2s",  ".s",
9113    [(set (v2i32 V64:$Rd),
9114       (OpNode (v2i32 V64:$Rn),
9115          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9116    bits<2> idx;
9117    let Inst{11} = idx{1};
9118    let Inst{21} = idx{0};
9119  }
9120
9121  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9122                                      V128, V128,
9123                                      V128, VectorIndexS,
9124                                      asm, ".4s", ".4s", ".4s", ".s",
9125    [(set (v4i32 V128:$Rd),
9126       (OpNode (v4i32 V128:$Rn),
9127          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9128    bits<2> idx;
9129    let Inst{11} = idx{1};
9130    let Inst{21} = idx{0};
9131  }
9132
9133  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9134                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9135                                      asm, ".h", "", "", ".h", []> {
9136    bits<3> idx;
9137    let Inst{11} = idx{2};
9138    let Inst{21} = idx{1};
9139    let Inst{20} = idx{0};
9140  }
9141
9142  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9143                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9144                                      asm, ".s", "", "", ".s",
9145      [(set (i32 FPR32Op:$Rd),
9146            (OpNode FPR32Op:$Rn,
9147                    (i32 (vector_extract (v4i32 V128:$Rm),
9148                                         VectorIndexS:$idx))))]> {
9149    bits<2> idx;
9150    let Inst{11} = idx{1};
9151    let Inst{21} = idx{0};
9152  }
9153}
9154
9155multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
9156                               SDPatternOperator OpNode> {
9157  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9158                                      V64, V64,
9159                                      V128_lo, VectorIndexH,
9160                                      asm, ".4h", ".4h", ".4h", ".h",
9161    [(set (v4i16 V64:$Rd),
9162        (OpNode (v4i16 V64:$Rn),
9163         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9164    bits<3> idx;
9165    let Inst{11} = idx{2};
9166    let Inst{21} = idx{1};
9167    let Inst{20} = idx{0};
9168  }
9169
9170  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9171                                      V128, V128,
9172                                      V128_lo, VectorIndexH,
9173                                      asm, ".8h", ".8h", ".8h", ".h",
9174    [(set (v8i16 V128:$Rd),
9175       (OpNode (v8i16 V128:$Rn),
9176         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9177    bits<3> idx;
9178    let Inst{11} = idx{2};
9179    let Inst{21} = idx{1};
9180    let Inst{20} = idx{0};
9181  }
9182
9183  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9184                                      V64, V64,
9185                                      V128, VectorIndexS,
9186                                      asm, ".2s", ".2s", ".2s", ".s",
9187    [(set (v2i32 V64:$Rd),
9188       (OpNode (v2i32 V64:$Rn),
9189          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9190    bits<2> idx;
9191    let Inst{11} = idx{1};
9192    let Inst{21} = idx{0};
9193  }
9194
9195  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9196                                      V128, V128,
9197                                      V128, VectorIndexS,
9198                                      asm, ".4s", ".4s", ".4s", ".s",
9199    [(set (v4i32 V128:$Rd),
9200       (OpNode (v4i32 V128:$Rn),
9201          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9202    bits<2> idx;
9203    let Inst{11} = idx{1};
9204    let Inst{21} = idx{0};
9205  }
9206}
9207
9208multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
9209                                   SDPatternOperator OpNode> {
9210  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
9211                                          V128_lo, VectorIndexH,
9212                                          asm, ".4h", ".4h", ".4h", ".h",
9213    [(set (v4i16 V64:$dst),
9214        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
9215         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9216    bits<3> idx;
9217    let Inst{11} = idx{2};
9218    let Inst{21} = idx{1};
9219    let Inst{20} = idx{0};
9220  }
9221
9222  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9223                                      V128, V128,
9224                                      V128_lo, VectorIndexH,
9225                                      asm, ".8h", ".8h", ".8h", ".h",
9226    [(set (v8i16 V128:$dst),
9227       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9228         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9229    bits<3> idx;
9230    let Inst{11} = idx{2};
9231    let Inst{21} = idx{1};
9232    let Inst{20} = idx{0};
9233  }
9234
9235  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9236                                      V64, V64,
9237                                      V128, VectorIndexS,
9238                                      asm, ".2s", ".2s", ".2s", ".s",
9239    [(set (v2i32 V64:$dst),
9240       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9241          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9242    bits<2> idx;
9243    let Inst{11} = idx{1};
9244    let Inst{21} = idx{0};
9245  }
9246
9247  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9248                                      V128, V128,
9249                                      V128, VectorIndexS,
9250                                      asm, ".4s", ".4s", ".4s", ".s",
9251    [(set (v4i32 V128:$dst),
9252       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9253          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9254    bits<2> idx;
9255    let Inst{11} = idx{1};
9256    let Inst{21} = idx{0};
9257  }
9258}
9259
9260multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
9261                             SDPatternOperator OpNode> {
9262  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9263                                      V128, V64,
9264                                      V128_lo, VectorIndexH,
9265                                      asm, ".4s", ".4s", ".4h", ".h",
9266    [(set (v4i32 V128:$Rd),
9267        (OpNode (v4i16 V64:$Rn),
9268         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9269    bits<3> idx;
9270    let Inst{11} = idx{2};
9271    let Inst{21} = idx{1};
9272    let Inst{20} = idx{0};
9273  }
9274
9275  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9276                                      V128, V128,
9277                                      V128_lo, VectorIndexH,
9278                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9279    [(set (v4i32 V128:$Rd),
9280          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9281                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9282
9283    bits<3> idx;
9284    let Inst{11} = idx{2};
9285    let Inst{21} = idx{1};
9286    let Inst{20} = idx{0};
9287  }
9288
9289  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9290                                      V128, V64,
9291                                      V128, VectorIndexS,
9292                                      asm, ".2d", ".2d", ".2s", ".s",
9293    [(set (v2i64 V128:$Rd),
9294        (OpNode (v2i32 V64:$Rn),
9295         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9296    bits<2> idx;
9297    let Inst{11} = idx{1};
9298    let Inst{21} = idx{0};
9299  }
9300
9301  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9302                                      V128, V128,
9303                                      V128, VectorIndexS,
9304                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9305    [(set (v2i64 V128:$Rd),
9306          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9307                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9308    bits<2> idx;
9309    let Inst{11} = idx{1};
9310    let Inst{21} = idx{0};
9311  }
9312
9313  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9314                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9315                                      asm, ".h", "", "", ".h", []> {
9316    bits<3> idx;
9317    let Inst{11} = idx{2};
9318    let Inst{21} = idx{1};
9319    let Inst{20} = idx{0};
9320  }
9321
9322  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9323                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9324                                      asm, ".s", "", "", ".s", []> {
9325    bits<2> idx;
9326    let Inst{11} = idx{1};
9327    let Inst{21} = idx{0};
9328  }
9329}
9330
9331multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
9332                                       SDPatternOperator Accum> {
9333  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9334                                      V128, V64,
9335                                      V128_lo, VectorIndexH,
9336                                      asm, ".4s", ".4s", ".4h", ".h",
9337    [(set (v4i32 V128:$dst),
9338          (Accum (v4i32 V128:$Rd),
9339                 (v4i32 (int_aarch64_neon_sqdmull
9340                             (v4i16 V64:$Rn),
9341                             (dup_v8i16 (v8i16 V128_lo:$Rm),
9342                                         VectorIndexH:$idx)))))]> {
9343    bits<3> idx;
9344    let Inst{11} = idx{2};
9345    let Inst{21} = idx{1};
9346    let Inst{20} = idx{0};
9347  }
9348
9349  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9350                                      V128, V128,
9351                                      V128_lo, VectorIndexH,
9352                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9353    [(set (v4i32 V128:$dst),
9354          (Accum (v4i32 V128:$Rd),
9355                 (v4i32 (int_aarch64_neon_sqdmull
9356                            (extract_high_v8i16 (v8i16 V128:$Rn)),
9357                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
9358    bits<3> idx;
9359    let Inst{11} = idx{2};
9360    let Inst{21} = idx{1};
9361    let Inst{20} = idx{0};
9362  }
9363
9364  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9365                                      V128, V64,
9366                                      V128, VectorIndexS,
9367                                      asm, ".2d", ".2d", ".2s", ".s",
9368    [(set (v2i64 V128:$dst),
9369        (Accum (v2i64 V128:$Rd),
9370               (v2i64 (int_aarch64_neon_sqdmull
9371                          (v2i32 V64:$Rn),
9372                          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9373    bits<2> idx;
9374    let Inst{11} = idx{1};
9375    let Inst{21} = idx{0};
9376  }
9377
9378  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9379                                      V128, V128,
9380                                      V128, VectorIndexS,
9381                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9382    [(set (v2i64 V128:$dst),
9383          (Accum (v2i64 V128:$Rd),
9384                 (v2i64 (int_aarch64_neon_sqdmull
9385                            (extract_high_v4i32 (v4i32 V128:$Rn)),
9386                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9387    bits<2> idx;
9388    let Inst{11} = idx{1};
9389    let Inst{21} = idx{0};
9390  }
9391
9392  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9393                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9394                                      asm, ".h", "", "", ".h", []> {
9395    bits<3> idx;
9396    let Inst{11} = idx{2};
9397    let Inst{21} = idx{1};
9398    let Inst{20} = idx{0};
9399  }
9400
9401  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9402                        (i32 (vector_extract
9403                                    (v4i32 (int_aarch64_neon_sqdmull
9404                                                (v4i16 V64:$Rn),
9405                                                (v4i16 V64:$Rm))),
9406                                    (i64 0))))),
9407            (!cast<Instruction>(NAME # v1i32_indexed)
9408                        FPR32Op:$Rd,
9409                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9410                        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rm, dsub),
9411                        (i64 0))>;
9412
9413  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9414                        (i32 (vector_extract
9415                                    (v4i32 (int_aarch64_neon_sqdmull
9416                                                (v4i16 V64:$Rn),
9417                                                (dup_v8i16 (v8i16 V128_lo:$Rm),
9418                                                            VectorIndexH:$idx))),
9419                                    (i64 0))))),
9420            (!cast<Instruction>(NAME # v1i32_indexed)
9421                        FPR32Op:$Rd,
9422                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9423                        V128_lo:$Rm,
9424                        VectorIndexH:$idx)>;
9425
9426  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9427                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9428                                      asm, ".s", "", "", ".s",
9429    [(set (i64 FPR64Op:$dst),
9430          (Accum (i64 FPR64Op:$Rd),
9431                 (i64 (int_aarch64_neon_sqdmulls_scalar
9432                            (i32 FPR32Op:$Rn),
9433                            (i32 (vector_extract (v4i32 V128:$Rm),
9434                                                 VectorIndexS:$idx))))))]> {
9435
9436    bits<2> idx;
9437    let Inst{11} = idx{1};
9438    let Inst{21} = idx{0};
9439  }
9440}
9441
9442multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
9443                                   SDPatternOperator OpNode> {
9444  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9445  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9446                                      V128, V64,
9447                                      V128_lo, VectorIndexH,
9448                                      asm, ".4s", ".4s", ".4h", ".h",
9449    [(set (v4i32 V128:$Rd),
9450        (OpNode (v4i16 V64:$Rn),
9451         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9452    bits<3> idx;
9453    let Inst{11} = idx{2};
9454    let Inst{21} = idx{1};
9455    let Inst{20} = idx{0};
9456  }
9457
9458  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9459                                      V128, V128,
9460                                      V128_lo, VectorIndexH,
9461                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9462    [(set (v4i32 V128:$Rd),
9463          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9464                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9465
9466    bits<3> idx;
9467    let Inst{11} = idx{2};
9468    let Inst{21} = idx{1};
9469    let Inst{20} = idx{0};
9470  }
9471
9472  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9473                                      V128, V64,
9474                                      V128, VectorIndexS,
9475                                      asm, ".2d", ".2d", ".2s", ".s",
9476    [(set (v2i64 V128:$Rd),
9477        (OpNode (v2i32 V64:$Rn),
9478         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9479    bits<2> idx;
9480    let Inst{11} = idx{1};
9481    let Inst{21} = idx{0};
9482  }
9483
9484  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9485                                      V128, V128,
9486                                      V128, VectorIndexS,
9487                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9488    [(set (v2i64 V128:$Rd),
9489          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9490                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9491    bits<2> idx;
9492    let Inst{11} = idx{1};
9493    let Inst{21} = idx{0};
9494  }
9495  }
9496}
9497
9498multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
9499                                       SDPatternOperator OpNode> {
9500  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9501  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9502                                      V128, V64,
9503                                      V128_lo, VectorIndexH,
9504                                      asm, ".4s", ".4s", ".4h", ".h",
9505    [(set (v4i32 V128:$dst),
9506        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
9507         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9508    bits<3> idx;
9509    let Inst{11} = idx{2};
9510    let Inst{21} = idx{1};
9511    let Inst{20} = idx{0};
9512  }
9513
9514  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9515                                      V128, V128,
9516                                      V128_lo, VectorIndexH,
9517                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9518    [(set (v4i32 V128:$dst),
9519          (OpNode (v4i32 V128:$Rd),
9520                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9521                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9522    bits<3> idx;
9523    let Inst{11} = idx{2};
9524    let Inst{21} = idx{1};
9525    let Inst{20} = idx{0};
9526  }
9527
9528  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9529                                      V128, V64,
9530                                      V128, VectorIndexS,
9531                                      asm, ".2d", ".2d", ".2s", ".s",
9532    [(set (v2i64 V128:$dst),
9533        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9534         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9535    bits<2> idx;
9536    let Inst{11} = idx{1};
9537    let Inst{21} = idx{0};
9538  }
9539
9540  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9541                                      V128, V128,
9542                                      V128, VectorIndexS,
9543                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9544    [(set (v2i64 V128:$dst),
9545          (OpNode (v2i64 V128:$Rd),
9546                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9547                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9548    bits<2> idx;
9549    let Inst{11} = idx{1};
9550    let Inst{21} = idx{0};
9551  }
9552  }
9553}
9554
9555//----------------------------------------------------------------------------
9556// AdvSIMD scalar shift by immediate
9557//----------------------------------------------------------------------------
9558
9559let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9560class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9561                     RegisterClass regtype1, RegisterClass regtype2,
9562                     Operand immtype, string asm, list<dag> pattern>
9563  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9564      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9565    Sched<[WriteVd]> {
9566  bits<5> Rd;
9567  bits<5> Rn;
9568  bits<7> imm;
9569  let Inst{31-30} = 0b01;
9570  let Inst{29}    = U;
9571  let Inst{28-23} = 0b111110;
9572  let Inst{22-16} = fixed_imm;
9573  let Inst{15-11} = opc;
9574  let Inst{10}    = 1;
9575  let Inst{9-5} = Rn;
9576  let Inst{4-0} = Rd;
9577}
9578
9579let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9580class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9581                     RegisterClass regtype1, RegisterClass regtype2,
9582                     Operand immtype, string asm, list<dag> pattern>
9583  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9584      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9585    Sched<[WriteVd]> {
9586  bits<5> Rd;
9587  bits<5> Rn;
9588  bits<7> imm;
9589  let Inst{31-30} = 0b01;
9590  let Inst{29}    = U;
9591  let Inst{28-23} = 0b111110;
9592  let Inst{22-16} = fixed_imm;
9593  let Inst{15-11} = opc;
9594  let Inst{10}    = 1;
9595  let Inst{9-5} = Rn;
9596  let Inst{4-0} = Rd;
9597}
9598
9599
9600multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9601  let Predicates = [HasNEON, HasFullFP16] in {
9602  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9603                              FPR16, FPR16, vecshiftR16, asm, []> {
9604    let Inst{19-16} = imm{3-0};
9605  }
9606  } // Predicates = [HasNEON, HasFullFP16]
9607  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9608                              FPR32, FPR32, vecshiftR32, asm, []> {
9609    let Inst{20-16} = imm{4-0};
9610  }
9611  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9612                              FPR64, FPR64, vecshiftR64, asm, []> {
9613    let Inst{21-16} = imm{5-0};
9614  }
9615}
9616
9617multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9618                             SDPatternOperator OpNode> {
9619  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9620                              FPR64, FPR64, vecshiftR64, asm,
9621  [(set (i64 FPR64:$Rd),
9622     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9623    let Inst{21-16} = imm{5-0};
9624  }
9625
9626  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9627            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9628}
9629
9630multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9631                                 SDPatternOperator OpNode = null_frag> {
9632  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9633                              FPR64, FPR64, vecshiftR64, asm,
9634  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9635                                                   (i32 vecshiftR64:$imm)))]> {
9636    let Inst{21-16} = imm{5-0};
9637  }
9638
9639  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9640                           (i32 vecshiftR64:$imm))),
9641            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9642                                            vecshiftR64:$imm)>;
9643}
9644
9645multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9646                             SDPatternOperator OpNode> {
9647  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9648                              FPR64, FPR64, vecshiftL64, asm,
9649    [(set (i64 FPR64:$Rd),
9650       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9651    let Inst{21-16} = imm{5-0};
9652  }
9653
9654  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9655            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9656}
9657
9658let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9659multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9660  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9661                              FPR64, FPR64, vecshiftL64, asm, []> {
9662    let Inst{21-16} = imm{5-0};
9663  }
9664}
9665
9666let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9667multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9668                               SDPatternOperator OpNode = null_frag> {
9669  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9670                              FPR8, FPR16, vecshiftR8, asm, []> {
9671    let Inst{18-16} = imm{2-0};
9672  }
9673
9674  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9675                              FPR16, FPR32, vecshiftR16, asm, []> {
9676    let Inst{19-16} = imm{3-0};
9677  }
9678
9679  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9680                              FPR32, FPR64, vecshiftR32, asm,
9681    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9682    let Inst{20-16} = imm{4-0};
9683  }
9684}
9685
9686multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9687                                SDPatternOperator OpNode> {
9688  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9689                              FPR8, FPR8, vecshiftL8, asm, []> {
9690    let Inst{18-16} = imm{2-0};
9691  }
9692
9693  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9694                              FPR16, FPR16, vecshiftL16, asm, []> {
9695    let Inst{19-16} = imm{3-0};
9696  }
9697
9698  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9699                              FPR32, FPR32, vecshiftL32, asm,
9700    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9701    let Inst{20-16} = imm{4-0};
9702  }
9703
9704  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9705                              FPR64, FPR64, vecshiftL64, asm,
9706    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9707    let Inst{21-16} = imm{5-0};
9708  }
9709
9710  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9711            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9712}
9713
9714multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9715  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9716                              FPR8, FPR8, vecshiftR8, asm, []> {
9717    let Inst{18-16} = imm{2-0};
9718  }
9719
9720  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9721                              FPR16, FPR16, vecshiftR16, asm, []> {
9722    let Inst{19-16} = imm{3-0};
9723  }
9724
9725  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9726                              FPR32, FPR32, vecshiftR32, asm, []> {
9727    let Inst{20-16} = imm{4-0};
9728  }
9729
9730  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9731                              FPR64, FPR64, vecshiftR64, asm, []> {
9732    let Inst{21-16} = imm{5-0};
9733  }
9734}
9735
9736//----------------------------------------------------------------------------
9737// AdvSIMD vector x indexed element
9738//----------------------------------------------------------------------------
9739
9740let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9741class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9742                     RegisterOperand dst_reg, RegisterOperand src_reg,
9743                     Operand immtype,
9744                     string asm, string dst_kind, string src_kind,
9745                     list<dag> pattern>
9746  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9747      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9748           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9749    Sched<[!if(Q, WriteVq, WriteVd)]> {
9750  bits<5> Rd;
9751  bits<5> Rn;
9752  let Inst{31}    = 0;
9753  let Inst{30}    = Q;
9754  let Inst{29}    = U;
9755  let Inst{28-23} = 0b011110;
9756  let Inst{22-16} = fixed_imm;
9757  let Inst{15-11} = opc;
9758  let Inst{10}    = 1;
9759  let Inst{9-5}   = Rn;
9760  let Inst{4-0}   = Rd;
9761}
9762
9763let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9764class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9765                     RegisterOperand vectype1, RegisterOperand vectype2,
9766                     Operand immtype,
9767                     string asm, string dst_kind, string src_kind,
9768                     list<dag> pattern>
9769  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9770      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9771           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9772    Sched<[!if(Q, WriteVq, WriteVd)]> {
9773  bits<5> Rd;
9774  bits<5> Rn;
9775  let Inst{31}    = 0;
9776  let Inst{30}    = Q;
9777  let Inst{29}    = U;
9778  let Inst{28-23} = 0b011110;
9779  let Inst{22-16} = fixed_imm;
9780  let Inst{15-11} = opc;
9781  let Inst{10}    = 1;
9782  let Inst{9-5}   = Rn;
9783  let Inst{4-0}   = Rd;
9784}
9785
9786multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9787                              Intrinsic OpNode> {
9788  let Predicates = [HasNEON, HasFullFP16] in {
9789  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9790                                  V64, V64, vecshiftR16,
9791                                  asm, ".4h", ".4h",
9792      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9793    bits<4> imm;
9794    let Inst{19-16} = imm;
9795  }
9796
9797  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9798                                  V128, V128, vecshiftR16,
9799                                  asm, ".8h", ".8h",
9800      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9801    bits<4> imm;
9802    let Inst{19-16} = imm;
9803  }
9804  } // Predicates = [HasNEON, HasFullFP16]
9805  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9806                                  V64, V64, vecshiftR32,
9807                                  asm, ".2s", ".2s",
9808      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9809    bits<5> imm;
9810    let Inst{20-16} = imm;
9811  }
9812
9813  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9814                                  V128, V128, vecshiftR32,
9815                                  asm, ".4s", ".4s",
9816      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9817    bits<5> imm;
9818    let Inst{20-16} = imm;
9819  }
9820
9821  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9822                                  V128, V128, vecshiftR64,
9823                                  asm, ".2d", ".2d",
9824      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9825    bits<6> imm;
9826    let Inst{21-16} = imm;
9827  }
9828}
9829
9830multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9831                                  Intrinsic OpNode> {
9832  let Predicates = [HasNEON, HasFullFP16] in {
9833  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9834                                  V64, V64, vecshiftR16,
9835                                  asm, ".4h", ".4h",
9836      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9837    bits<4> imm;
9838    let Inst{19-16} = imm;
9839  }
9840
9841  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9842                                  V128, V128, vecshiftR16,
9843                                  asm, ".8h", ".8h",
9844      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9845    bits<4> imm;
9846    let Inst{19-16} = imm;
9847  }
9848  } // Predicates = [HasNEON, HasFullFP16]
9849
9850  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9851                                  V64, V64, vecshiftR32,
9852                                  asm, ".2s", ".2s",
9853      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9854    bits<5> imm;
9855    let Inst{20-16} = imm;
9856  }
9857
9858  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9859                                  V128, V128, vecshiftR32,
9860                                  asm, ".4s", ".4s",
9861      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9862    bits<5> imm;
9863    let Inst{20-16} = imm;
9864  }
9865
9866  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9867                                  V128, V128, vecshiftR64,
9868                                  asm, ".2d", ".2d",
9869      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9870    bits<6> imm;
9871    let Inst{21-16} = imm;
9872  }
9873}
9874
9875multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9876                                     SDPatternOperator OpNode> {
9877  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9878                                  V64, V128, vecshiftR16Narrow,
9879                                  asm, ".8b", ".8h",
9880      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9881    bits<3> imm;
9882    let Inst{18-16} = imm;
9883  }
9884
9885  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9886                                  V128, V128, vecshiftR16Narrow,
9887                                  asm#"2", ".16b", ".8h", []> {
9888    bits<3> imm;
9889    let Inst{18-16} = imm;
9890    let hasSideEffects = 0;
9891  }
9892
9893  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9894                                  V64, V128, vecshiftR32Narrow,
9895                                  asm, ".4h", ".4s",
9896      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9897    bits<4> imm;
9898    let Inst{19-16} = imm;
9899  }
9900
9901  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9902                                  V128, V128, vecshiftR32Narrow,
9903                                  asm#"2", ".8h", ".4s", []> {
9904    bits<4> imm;
9905    let Inst{19-16} = imm;
9906    let hasSideEffects = 0;
9907  }
9908
9909  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9910                                  V64, V128, vecshiftR64Narrow,
9911                                  asm, ".2s", ".2d",
9912      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9913    bits<5> imm;
9914    let Inst{20-16} = imm;
9915  }
9916
9917  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9918                                  V128, V128, vecshiftR64Narrow,
9919                                  asm#"2", ".4s", ".2d", []> {
9920    bits<5> imm;
9921    let Inst{20-16} = imm;
9922    let hasSideEffects = 0;
9923  }
9924
9925  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9926  // themselves, so put them here instead.
9927
9928  // Patterns involving what's effectively an insert high and a normal
9929  // intrinsic, represented by CONCAT_VECTORS.
9930  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9931                                                   vecshiftR16Narrow:$imm)),
9932            (!cast<Instruction>(NAME # "v16i8_shift")
9933                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9934                V128:$Rn, vecshiftR16Narrow:$imm)>;
9935  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9936                                                     vecshiftR32Narrow:$imm)),
9937            (!cast<Instruction>(NAME # "v8i16_shift")
9938                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9939                V128:$Rn, vecshiftR32Narrow:$imm)>;
9940  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9941                                                     vecshiftR64Narrow:$imm)),
9942            (!cast<Instruction>(NAME # "v4i32_shift")
9943                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9944                V128:$Rn, vecshiftR64Narrow:$imm)>;
9945}
9946
9947multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9948                                SDPatternOperator OpNode> {
9949  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9950                                  V64, V64, vecshiftL8,
9951                                  asm, ".8b", ".8b",
9952                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9953                       (i32 vecshiftL8:$imm)))]> {
9954    bits<3> imm;
9955    let Inst{18-16} = imm;
9956  }
9957
9958  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9959                                  V128, V128, vecshiftL8,
9960                                  asm, ".16b", ".16b",
9961             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9962                   (i32 vecshiftL8:$imm)))]> {
9963    bits<3> imm;
9964    let Inst{18-16} = imm;
9965  }
9966
9967  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9968                                  V64, V64, vecshiftL16,
9969                                  asm, ".4h", ".4h",
9970              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9971                    (i32 vecshiftL16:$imm)))]> {
9972    bits<4> imm;
9973    let Inst{19-16} = imm;
9974  }
9975
9976  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9977                                  V128, V128, vecshiftL16,
9978                                  asm, ".8h", ".8h",
9979            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9980                  (i32 vecshiftL16:$imm)))]> {
9981    bits<4> imm;
9982    let Inst{19-16} = imm;
9983  }
9984
9985  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9986                                  V64, V64, vecshiftL32,
9987                                  asm, ".2s", ".2s",
9988              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9989                    (i32 vecshiftL32:$imm)))]> {
9990    bits<5> imm;
9991    let Inst{20-16} = imm;
9992  }
9993
9994  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9995                                  V128, V128, vecshiftL32,
9996                                  asm, ".4s", ".4s",
9997            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9998                  (i32 vecshiftL32:$imm)))]> {
9999    bits<5> imm;
10000    let Inst{20-16} = imm;
10001  }
10002
10003  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10004                                  V128, V128, vecshiftL64,
10005                                  asm, ".2d", ".2d",
10006            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10007                  (i32 vecshiftL64:$imm)))]> {
10008    bits<6> imm;
10009    let Inst{21-16} = imm;
10010  }
10011}
10012
10013multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
10014                                SDPatternOperator OpNode> {
10015  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10016                                  V64, V64, vecshiftR8,
10017                                  asm, ".8b", ".8b",
10018                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10019                       (i32 vecshiftR8:$imm)))]> {
10020    bits<3> imm;
10021    let Inst{18-16} = imm;
10022  }
10023
10024  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10025                                  V128, V128, vecshiftR8,
10026                                  asm, ".16b", ".16b",
10027             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10028                   (i32 vecshiftR8:$imm)))]> {
10029    bits<3> imm;
10030    let Inst{18-16} = imm;
10031  }
10032
10033  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10034                                  V64, V64, vecshiftR16,
10035                                  asm, ".4h", ".4h",
10036              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10037                    (i32 vecshiftR16:$imm)))]> {
10038    bits<4> imm;
10039    let Inst{19-16} = imm;
10040  }
10041
10042  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10043                                  V128, V128, vecshiftR16,
10044                                  asm, ".8h", ".8h",
10045            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10046                  (i32 vecshiftR16:$imm)))]> {
10047    bits<4> imm;
10048    let Inst{19-16} = imm;
10049  }
10050
10051  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10052                                  V64, V64, vecshiftR32,
10053                                  asm, ".2s", ".2s",
10054              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10055                    (i32 vecshiftR32:$imm)))]> {
10056    bits<5> imm;
10057    let Inst{20-16} = imm;
10058  }
10059
10060  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10061                                  V128, V128, vecshiftR32,
10062                                  asm, ".4s", ".4s",
10063            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10064                  (i32 vecshiftR32:$imm)))]> {
10065    bits<5> imm;
10066    let Inst{20-16} = imm;
10067  }
10068
10069  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10070                                  V128, V128, vecshiftR64,
10071                                  asm, ".2d", ".2d",
10072            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10073                  (i32 vecshiftR64:$imm)))]> {
10074    bits<6> imm;
10075    let Inst{21-16} = imm;
10076  }
10077}
10078
10079let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10080multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
10081                                    SDPatternOperator OpNode = null_frag> {
10082  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10083                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
10084                 [(set (v8i8 V64:$dst),
10085                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10086                           (i32 vecshiftR8:$imm)))]> {
10087    bits<3> imm;
10088    let Inst{18-16} = imm;
10089  }
10090
10091  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10092                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
10093             [(set (v16i8 V128:$dst),
10094               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10095                       (i32 vecshiftR8:$imm)))]> {
10096    bits<3> imm;
10097    let Inst{18-16} = imm;
10098  }
10099
10100  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10101                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
10102              [(set (v4i16 V64:$dst),
10103                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10104                        (i32 vecshiftR16:$imm)))]> {
10105    bits<4> imm;
10106    let Inst{19-16} = imm;
10107  }
10108
10109  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10110                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
10111            [(set (v8i16 V128:$dst),
10112              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10113                      (i32 vecshiftR16:$imm)))]> {
10114    bits<4> imm;
10115    let Inst{19-16} = imm;
10116  }
10117
10118  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10119                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
10120              [(set (v2i32 V64:$dst),
10121                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10122                        (i32 vecshiftR32:$imm)))]> {
10123    bits<5> imm;
10124    let Inst{20-16} = imm;
10125  }
10126
10127  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10128                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
10129            [(set (v4i32 V128:$dst),
10130              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10131                      (i32 vecshiftR32:$imm)))]> {
10132    bits<5> imm;
10133    let Inst{20-16} = imm;
10134  }
10135
10136  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10137                                  V128, V128, vecshiftR64,
10138                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
10139              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10140                      (i32 vecshiftR64:$imm)))]> {
10141    bits<6> imm;
10142    let Inst{21-16} = imm;
10143  }
10144}
10145
10146multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
10147                                    SDPatternOperator OpNode = null_frag> {
10148  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10149                                  V64, V64, vecshiftL8,
10150                                  asm, ".8b", ".8b",
10151                    [(set (v8i8 V64:$dst),
10152                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10153                                  (i32 vecshiftL8:$imm)))]> {
10154    bits<3> imm;
10155    let Inst{18-16} = imm;
10156  }
10157
10158  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10159                                  V128, V128, vecshiftL8,
10160                                  asm, ".16b", ".16b",
10161                    [(set (v16i8 V128:$dst),
10162                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10163                                  (i32 vecshiftL8:$imm)))]> {
10164    bits<3> imm;
10165    let Inst{18-16} = imm;
10166  }
10167
10168  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10169                                  V64, V64, vecshiftL16,
10170                                  asm, ".4h", ".4h",
10171                    [(set (v4i16 V64:$dst),
10172                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10173                                   (i32 vecshiftL16:$imm)))]> {
10174    bits<4> imm;
10175    let Inst{19-16} = imm;
10176  }
10177
10178  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10179                                  V128, V128, vecshiftL16,
10180                                  asm, ".8h", ".8h",
10181                    [(set (v8i16 V128:$dst),
10182                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10183                                  (i32 vecshiftL16:$imm)))]> {
10184    bits<4> imm;
10185    let Inst{19-16} = imm;
10186  }
10187
10188  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10189                                  V64, V64, vecshiftL32,
10190                                  asm, ".2s", ".2s",
10191                    [(set (v2i32 V64:$dst),
10192                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10193                                  (i32 vecshiftL32:$imm)))]> {
10194    bits<5> imm;
10195    let Inst{20-16} = imm;
10196  }
10197
10198  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10199                                  V128, V128, vecshiftL32,
10200                                  asm, ".4s", ".4s",
10201                    [(set (v4i32 V128:$dst),
10202                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10203                                  (i32 vecshiftL32:$imm)))]> {
10204    bits<5> imm;
10205    let Inst{20-16} = imm;
10206  }
10207
10208  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10209                                  V128, V128, vecshiftL64,
10210                                  asm, ".2d", ".2d",
10211                    [(set (v2i64 V128:$dst),
10212                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10213                                  (i32 vecshiftL64:$imm)))]> {
10214    bits<6> imm;
10215    let Inst{21-16} = imm;
10216  }
10217}
10218
10219multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
10220                                   SDPatternOperator OpNode> {
10221  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10222                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
10223      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
10224    bits<3> imm;
10225    let Inst{18-16} = imm;
10226  }
10227
10228  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10229                                  V128, V128, vecshiftL8,
10230                                  asm#"2", ".8h", ".16b",
10231      [(set (v8i16 V128:$Rd),
10232            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
10233    bits<3> imm;
10234    let Inst{18-16} = imm;
10235  }
10236
10237  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10238                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
10239      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
10240    bits<4> imm;
10241    let Inst{19-16} = imm;
10242  }
10243
10244  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10245                                  V128, V128, vecshiftL16,
10246                                  asm#"2", ".4s", ".8h",
10247      [(set (v4i32 V128:$Rd),
10248            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
10249
10250    bits<4> imm;
10251    let Inst{19-16} = imm;
10252  }
10253
10254  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10255                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
10256      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
10257    bits<5> imm;
10258    let Inst{20-16} = imm;
10259  }
10260
10261  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10262                                  V128, V128, vecshiftL32,
10263                                  asm#"2", ".2d", ".4s",
10264      [(set (v2i64 V128:$Rd),
10265            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
10266    bits<5> imm;
10267    let Inst{20-16} = imm;
10268  }
10269}
10270
10271
10272//---
10273// Vector load/store
10274//---
10275// SIMD ldX/stX no-index memory references don't allow the optional
10276// ", #0" constant and handle post-indexing explicitly, so we use
10277// a more specialized parse method for them. Otherwise, it's the same as
10278// the general GPR64sp handling.
10279
10280class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
10281                   string asm, dag oops, dag iops, list<dag> pattern>
10282  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
10283  bits<5> Vt;
10284  bits<5> Rn;
10285  let Inst{31} = 0;
10286  let Inst{30} = Q;
10287  let Inst{29-23} = 0b0011000;
10288  let Inst{22} = L;
10289  let Inst{21-16} = 0b000000;
10290  let Inst{15-12} = opcode;
10291  let Inst{11-10} = size;
10292  let Inst{9-5} = Rn;
10293  let Inst{4-0} = Vt;
10294}
10295
10296class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
10297                       string asm, dag oops, dag iops>
10298  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
10299  bits<5> Vt;
10300  bits<5> Rn;
10301  bits<5> Xm;
10302  let Inst{31} = 0;
10303  let Inst{30} = Q;
10304  let Inst{29-23} = 0b0011001;
10305  let Inst{22} = L;
10306  let Inst{21} = 0;
10307  let Inst{20-16} = Xm;
10308  let Inst{15-12} = opcode;
10309  let Inst{11-10} = size;
10310  let Inst{9-5} = Rn;
10311  let Inst{4-0} = Vt;
10312}
10313
10314// The immediate form of AdvSIMD post-indexed addressing is encoded with
10315// register post-index addressing from the zero register.
10316multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
10317                           int Offset, int Size> {
10318  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
10319  //      "ld1\t$Vt, [$Rn], #16"
10320  // may get mapped to
10321  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
10322  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10323                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10324                      GPR64sp:$Rn,
10325                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10326                      XZR), 1>;
10327
10328  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
10329  //      "ld1.8b\t$Vt, [$Rn], #16"
10330  // may get mapped to
10331  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
10332  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10333                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10334                      GPR64sp:$Rn,
10335                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10336                      XZR), 0>;
10337
10338  // E.g. "ld1.8b { v0, v1 }, [x1]"
10339  //      "ld1\t$Vt, [$Rn]"
10340  // may get mapped to
10341  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
10342  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10343                  (!cast<Instruction>(BaseName # Count # "v" # layout)
10344                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10345                      GPR64sp:$Rn), 0>;
10346
10347  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
10348  //      "ld1\t$Vt, [$Rn], $Xm"
10349  // may get mapped to
10350  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
10351  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10352                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10353                      GPR64sp:$Rn,
10354                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10355                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10356}
10357
10358multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
10359                       int Offset128, int Offset64, bits<4> opcode> {
10360  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10361    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
10362                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
10363                           (ins GPR64sp:$Rn), []>;
10364    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
10365                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
10366                           (ins GPR64sp:$Rn), []>;
10367    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
10368                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
10369                           (ins GPR64sp:$Rn), []>;
10370    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
10371                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
10372                           (ins GPR64sp:$Rn), []>;
10373    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
10374                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
10375                           (ins GPR64sp:$Rn), []>;
10376    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
10377                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
10378                           (ins GPR64sp:$Rn), []>;
10379    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
10380                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
10381                           (ins GPR64sp:$Rn), []>;
10382
10383
10384    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
10385                       (outs GPR64sp:$wback,
10386                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
10387                       (ins GPR64sp:$Rn,
10388                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10389    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
10390                       (outs GPR64sp:$wback,
10391                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
10392                       (ins GPR64sp:$Rn,
10393                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10394    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
10395                       (outs GPR64sp:$wback,
10396                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
10397                       (ins GPR64sp:$Rn,
10398                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10399    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
10400                       (outs GPR64sp:$wback,
10401                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
10402                       (ins GPR64sp:$Rn,
10403                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10404    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
10405                       (outs GPR64sp:$wback,
10406                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
10407                       (ins GPR64sp:$Rn,
10408                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10409    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
10410                       (outs GPR64sp:$wback,
10411                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
10412                       (ins GPR64sp:$Rn,
10413                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10414    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
10415                       (outs GPR64sp:$wback,
10416                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
10417                       (ins GPR64sp:$Rn,
10418                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10419  }
10420
10421  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10422  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10423  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10424  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10425  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10426  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10427  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10428}
10429
10430// Only ld1/st1 has a v1d version.
10431multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
10432                       int Offset128, int Offset64, bits<4> opcode> {
10433  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
10434    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
10435                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10436                                 GPR64sp:$Rn), []>;
10437    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
10438                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10439                                GPR64sp:$Rn), []>;
10440    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
10441                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10442                                GPR64sp:$Rn), []>;
10443    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
10444                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10445                                GPR64sp:$Rn), []>;
10446    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
10447                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10448                                GPR64sp:$Rn), []>;
10449    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
10450                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10451                                GPR64sp:$Rn), []>;
10452    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
10453                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10454                                GPR64sp:$Rn), []>;
10455
10456    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
10457                       (outs GPR64sp:$wback),
10458                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10459                            GPR64sp:$Rn,
10460                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10461    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
10462                       (outs GPR64sp:$wback),
10463                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10464                            GPR64sp:$Rn,
10465                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10466    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
10467                       (outs GPR64sp:$wback),
10468                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10469                            GPR64sp:$Rn,
10470                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10471    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
10472                       (outs GPR64sp:$wback),
10473                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10474                            GPR64sp:$Rn,
10475                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10476    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
10477                       (outs GPR64sp:$wback),
10478                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10479                            GPR64sp:$Rn,
10480                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10481    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
10482                       (outs GPR64sp:$wback),
10483                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10484                            GPR64sp:$Rn,
10485                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10486    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
10487                       (outs GPR64sp:$wback),
10488                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10489                            GPR64sp:$Rn,
10490                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10491  }
10492
10493  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10494  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10495  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10496  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10497  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10498  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10499  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10500}
10501
10502multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
10503                       int Offset128, int Offset64, bits<4> opcode>
10504  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10505
10506  // LD1 instructions have extra "1d" variants.
10507  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10508    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
10509                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10510                           (ins GPR64sp:$Rn), []>;
10511
10512    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10513                       (outs GPR64sp:$wback,
10514                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10515                       (ins GPR64sp:$Rn,
10516                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10517  }
10518
10519  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10520}
10521
10522multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10523                       int Offset128, int Offset64, bits<4> opcode>
10524  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10525
10526  // ST1 instructions have extra "1d" variants.
10527  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10528    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10529                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10530                                GPR64sp:$Rn), []>;
10531
10532    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10533                       (outs GPR64sp:$wback),
10534                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10535                            GPR64sp:$Rn,
10536                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10537  }
10538
10539  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10540}
10541
10542multiclass SIMDLd1Multiple<string asm> {
10543  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10544  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10545  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10546  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10547}
10548
10549multiclass SIMDSt1Multiple<string asm> {
10550  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10551  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10552  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10553  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10554}
10555
10556multiclass SIMDLd2Multiple<string asm> {
10557  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10558}
10559
10560multiclass SIMDSt2Multiple<string asm> {
10561  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10562}
10563
10564multiclass SIMDLd3Multiple<string asm> {
10565  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10566}
10567
10568multiclass SIMDSt3Multiple<string asm> {
10569  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10570}
10571
10572multiclass SIMDLd4Multiple<string asm> {
10573  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10574}
10575
10576multiclass SIMDSt4Multiple<string asm> {
10577  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10578}
10579
10580//---
10581// AdvSIMD Load/store single-element
10582//---
10583
10584class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10585                         string asm, string operands, string cst,
10586                         dag oops, dag iops, list<dag> pattern>
10587  : I<oops, iops, asm, operands, cst, pattern> {
10588  bits<5> Vt;
10589  bits<5> Rn;
10590  let Inst{31} = 0;
10591  let Inst{29-24} = 0b001101;
10592  let Inst{22} = L;
10593  let Inst{21} = R;
10594  let Inst{15-13} = opcode;
10595  let Inst{9-5} = Rn;
10596  let Inst{4-0} = Vt;
10597}
10598
10599class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10600                         string asm, string operands, string cst,
10601                         dag oops, dag iops, list<dag> pattern>
10602  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10603  bits<5> Vt;
10604  bits<5> Rn;
10605  let Inst{31} = 0;
10606  let Inst{29-24} = 0b001101;
10607  let Inst{22} = L;
10608  let Inst{21} = R;
10609  let Inst{15-13} = opcode;
10610  let Inst{9-5} = Rn;
10611  let Inst{4-0} = Vt;
10612}
10613
10614
10615let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10616class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10617                  DAGOperand listtype>
10618  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10619                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10620                       []> {
10621  let Inst{30} = Q;
10622  let Inst{23} = 0;
10623  let Inst{20-16} = 0b00000;
10624  let Inst{12} = S;
10625  let Inst{11-10} = size;
10626}
10627let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10628class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10629                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10630  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10631                       "$Rn = $wback",
10632                       (outs GPR64sp:$wback, listtype:$Vt),
10633                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10634  bits<5> Xm;
10635  let Inst{30} = Q;
10636  let Inst{23} = 1;
10637  let Inst{20-16} = Xm;
10638  let Inst{12} = S;
10639  let Inst{11-10} = size;
10640}
10641
10642multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10643                          int Offset, int Size> {
10644  // E.g. "ld1r { v0.8b }, [x1], #1"
10645  //      "ld1r.8b\t$Vt, [$Rn], #1"
10646  // may get mapped to
10647  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10648  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10649                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10650                      GPR64sp:$Rn,
10651                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10652                      XZR), 1>;
10653
10654  // E.g. "ld1r.8b { v0 }, [x1], #1"
10655  //      "ld1r.8b\t$Vt, [$Rn], #1"
10656  // may get mapped to
10657  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10658  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10659                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10660                      GPR64sp:$Rn,
10661                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10662                      XZR), 0>;
10663
10664  // E.g. "ld1r.8b { v0 }, [x1]"
10665  //      "ld1r.8b\t$Vt, [$Rn]"
10666  // may get mapped to
10667  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10668  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10669                  (!cast<Instruction>(BaseName # "v" # layout)
10670                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10671                      GPR64sp:$Rn), 0>;
10672
10673  // E.g. "ld1r.8b { v0 }, [x1], x2"
10674  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10675  // may get mapped to
10676  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10677  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10678                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10679                      GPR64sp:$Rn,
10680                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10681                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10682}
10683
10684multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10685  int Offset1, int Offset2, int Offset4, int Offset8> {
10686  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10687                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10688  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10689                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10690  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10691                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10692  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10693                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10694  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10695                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10696  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10697                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10698  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10699                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10700  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10701                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10702
10703  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10704                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10705                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10706  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10707                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10708                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10709  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10710                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10711                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10712  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10713                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10714                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10715  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10716                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10717                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10718  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10719                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10720                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10721  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10722                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10723                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10724  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10725                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10726                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10727
10728  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10729  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10730  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10731  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10732  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10733  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10734  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10735  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10736}
10737
10738class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10739                      dag oops, dag iops, list<dag> pattern>
10740  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10741                       pattern> {
10742  // idx encoded in Q:S:size fields.
10743  bits<4> idx;
10744  let Inst{30} = idx{3};
10745  let Inst{23} = 0;
10746  let Inst{20-16} = 0b00000;
10747  let Inst{12} = idx{2};
10748  let Inst{11-10} = idx{1-0};
10749}
10750class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10751                      dag oops, dag iops, list<dag> pattern>
10752  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10753                           oops, iops, pattern> {
10754  // idx encoded in Q:S:size fields.
10755  bits<4> idx;
10756  let Inst{30} = idx{3};
10757  let Inst{23} = 0;
10758  let Inst{20-16} = 0b00000;
10759  let Inst{12} = idx{2};
10760  let Inst{11-10} = idx{1-0};
10761}
10762class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10763                          dag oops, dag iops>
10764  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10765                       "$Rn = $wback", oops, iops, []> {
10766  // idx encoded in Q:S:size fields.
10767  bits<4> idx;
10768  bits<5> Xm;
10769  let Inst{30} = idx{3};
10770  let Inst{23} = 1;
10771  let Inst{20-16} = Xm;
10772  let Inst{12} = idx{2};
10773  let Inst{11-10} = idx{1-0};
10774}
10775class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10776                          dag oops, dag iops>
10777  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10778                           "$Rn = $wback", oops, iops, []> {
10779  // idx encoded in Q:S:size fields.
10780  bits<4> idx;
10781  bits<5> Xm;
10782  let Inst{30} = idx{3};
10783  let Inst{23} = 1;
10784  let Inst{20-16} = Xm;
10785  let Inst{12} = idx{2};
10786  let Inst{11-10} = idx{1-0};
10787}
10788
10789class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10790                      dag oops, dag iops, list<dag> pattern>
10791  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10792                       pattern> {
10793  // idx encoded in Q:S:size<1> fields.
10794  bits<3> idx;
10795  let Inst{30} = idx{2};
10796  let Inst{23} = 0;
10797  let Inst{20-16} = 0b00000;
10798  let Inst{12} = idx{1};
10799  let Inst{11} = idx{0};
10800  let Inst{10} = size;
10801}
10802class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10803                      dag oops, dag iops, list<dag> pattern>
10804  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10805                           oops, iops, pattern> {
10806  // idx encoded in Q:S:size<1> fields.
10807  bits<3> idx;
10808  let Inst{30} = idx{2};
10809  let Inst{23} = 0;
10810  let Inst{20-16} = 0b00000;
10811  let Inst{12} = idx{1};
10812  let Inst{11} = idx{0};
10813  let Inst{10} = size;
10814}
10815
10816class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10817                          dag oops, dag iops>
10818  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10819                       "$Rn = $wback", oops, iops, []> {
10820  // idx encoded in Q:S:size<1> fields.
10821  bits<3> idx;
10822  bits<5> Xm;
10823  let Inst{30} = idx{2};
10824  let Inst{23} = 1;
10825  let Inst{20-16} = Xm;
10826  let Inst{12} = idx{1};
10827  let Inst{11} = idx{0};
10828  let Inst{10} = size;
10829}
10830class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10831                          dag oops, dag iops>
10832  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10833                           "$Rn = $wback", oops, iops, []> {
10834  // idx encoded in Q:S:size<1> fields.
10835  bits<3> idx;
10836  bits<5> Xm;
10837  let Inst{30} = idx{2};
10838  let Inst{23} = 1;
10839  let Inst{20-16} = Xm;
10840  let Inst{12} = idx{1};
10841  let Inst{11} = idx{0};
10842  let Inst{10} = size;
10843}
10844class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10845                      dag oops, dag iops, list<dag> pattern>
10846  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10847                       pattern> {
10848  // idx encoded in Q:S fields.
10849  bits<2> idx;
10850  let Inst{30} = idx{1};
10851  let Inst{23} = 0;
10852  let Inst{20-16} = 0b00000;
10853  let Inst{12} = idx{0};
10854  let Inst{11-10} = size;
10855}
10856class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10857                      dag oops, dag iops, list<dag> pattern>
10858  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10859                           oops, iops, pattern> {
10860  // idx encoded in Q:S fields.
10861  bits<2> idx;
10862  let Inst{30} = idx{1};
10863  let Inst{23} = 0;
10864  let Inst{20-16} = 0b00000;
10865  let Inst{12} = idx{0};
10866  let Inst{11-10} = size;
10867}
10868class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10869                          string asm, dag oops, dag iops>
10870  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10871                       "$Rn = $wback", oops, iops, []> {
10872  // idx encoded in Q:S fields.
10873  bits<2> idx;
10874  bits<5> Xm;
10875  let Inst{30} = idx{1};
10876  let Inst{23} = 1;
10877  let Inst{20-16} = Xm;
10878  let Inst{12} = idx{0};
10879  let Inst{11-10} = size;
10880}
10881class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10882                          string asm, dag oops, dag iops>
10883  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10884                           "$Rn = $wback", oops, iops, []> {
10885  // idx encoded in Q:S fields.
10886  bits<2> idx;
10887  bits<5> Xm;
10888  let Inst{30} = idx{1};
10889  let Inst{23} = 1;
10890  let Inst{20-16} = Xm;
10891  let Inst{12} = idx{0};
10892  let Inst{11-10} = size;
10893}
10894class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10895                      dag oops, dag iops, list<dag> pattern>
10896  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10897                       pattern> {
10898  // idx encoded in Q field.
10899  bits<1> idx;
10900  let Inst{30} = idx;
10901  let Inst{23} = 0;
10902  let Inst{20-16} = 0b00000;
10903  let Inst{12} = 0;
10904  let Inst{11-10} = size;
10905}
10906class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10907                      dag oops, dag iops, list<dag> pattern>
10908  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10909                           oops, iops, pattern> {
10910  // idx encoded in Q field.
10911  bits<1> idx;
10912  let Inst{30} = idx;
10913  let Inst{23} = 0;
10914  let Inst{20-16} = 0b00000;
10915  let Inst{12} = 0;
10916  let Inst{11-10} = size;
10917}
10918class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10919                          string asm, dag oops, dag iops>
10920  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10921                       "$Rn = $wback", oops, iops, []> {
10922  // idx encoded in Q field.
10923  bits<1> idx;
10924  bits<5> Xm;
10925  let Inst{30} = idx;
10926  let Inst{23} = 1;
10927  let Inst{20-16} = Xm;
10928  let Inst{12} = 0;
10929  let Inst{11-10} = size;
10930}
10931class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10932                          string asm, dag oops, dag iops>
10933  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10934                           "$Rn = $wback", oops, iops, []> {
10935  // idx encoded in Q field.
10936  bits<1> idx;
10937  bits<5> Xm;
10938  let Inst{30} = idx;
10939  let Inst{23} = 1;
10940  let Inst{20-16} = Xm;
10941  let Inst{12} = 0;
10942  let Inst{11-10} = size;
10943}
10944
10945let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10946multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10947                         RegisterOperand listtype,
10948                         RegisterOperand GPR64pi> {
10949  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10950                           (outs listtype:$dst),
10951                           (ins listtype:$Vt, VectorIndexB:$idx,
10952                                GPR64sp:$Rn), []>;
10953
10954  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10955                            (outs GPR64sp:$wback, listtype:$dst),
10956                            (ins listtype:$Vt, VectorIndexB:$idx,
10957                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10958}
10959let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10960multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10961                         RegisterOperand listtype,
10962                         RegisterOperand GPR64pi> {
10963  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10964                            (outs listtype:$dst),
10965                            (ins listtype:$Vt, VectorIndexH:$idx,
10966                                 GPR64sp:$Rn), []>;
10967
10968  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10969                            (outs GPR64sp:$wback, listtype:$dst),
10970                            (ins listtype:$Vt, VectorIndexH:$idx,
10971                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10972}
10973let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10974multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10975                         RegisterOperand listtype,
10976                         RegisterOperand GPR64pi> {
10977  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10978                            (outs listtype:$dst),
10979                            (ins listtype:$Vt, VectorIndexS:$idx,
10980                                 GPR64sp:$Rn), []>;
10981
10982  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10983                            (outs GPR64sp:$wback, listtype:$dst),
10984                            (ins listtype:$Vt, VectorIndexS:$idx,
10985                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10986}
10987let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10988multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10989                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10990  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10991                            (outs listtype:$dst),
10992                            (ins listtype:$Vt, VectorIndexD:$idx,
10993                                 GPR64sp:$Rn), []>;
10994
10995  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10996                            (outs GPR64sp:$wback, listtype:$dst),
10997                            (ins listtype:$Vt, VectorIndexD:$idx,
10998                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10999}
11000let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11001multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
11002                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11003  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
11004                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
11005                                        GPR64sp:$Rn), []>;
11006
11007  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
11008                                    (outs GPR64sp:$wback),
11009                                    (ins listtype:$Vt, VectorIndexB:$idx,
11010                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
11011}
11012let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11013multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
11014                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11015  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
11016                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
11017                                         GPR64sp:$Rn), []>;
11018
11019  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
11020                            (outs GPR64sp:$wback),
11021                            (ins listtype:$Vt, VectorIndexH:$idx,
11022                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11023}
11024let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11025multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
11026                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11027  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
11028                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
11029                                         GPR64sp:$Rn), []>;
11030
11031  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
11032                            (outs GPR64sp:$wback),
11033                            (ins listtype:$Vt, VectorIndexS:$idx,
11034                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11035}
11036let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11037multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
11038                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11039  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
11040                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
11041                                         GPR64sp:$Rn), []>;
11042
11043  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
11044                            (outs GPR64sp:$wback),
11045                            (ins listtype:$Vt, VectorIndexD:$idx,
11046                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11047}
11048
11049multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
11050                                 string Count, int Offset, Operand idxtype> {
11051  // E.g. "ld1 { v0.8b }[0], [x1], #1"
11052  //      "ld1\t$Vt, [$Rn], #1"
11053  // may get mapped to
11054  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
11055  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
11056                  (!cast<Instruction>(NAME # Type  # "_POST")
11057                      GPR64sp:$Rn,
11058                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
11059                      idxtype:$idx, XZR), 1>;
11060
11061  // E.g. "ld1.8b { v0 }[0], [x1], #1"
11062  //      "ld1.8b\t$Vt, [$Rn], #1"
11063  // may get mapped to
11064  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
11065  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
11066                  (!cast<Instruction>(NAME # Type # "_POST")
11067                      GPR64sp:$Rn,
11068                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11069                      idxtype:$idx, XZR), 0>;
11070
11071  // E.g. "ld1.8b { v0 }[0], [x1]"
11072  //      "ld1.8b\t$Vt, [$Rn]"
11073  // may get mapped to
11074  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
11075  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
11076                      (!cast<Instruction>(NAME # Type)
11077                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11078                         idxtype:$idx, GPR64sp:$Rn), 0>;
11079
11080  // E.g. "ld1.8b { v0 }[0], [x1], x2"
11081  //      "ld1.8b\t$Vt, [$Rn], $Xm"
11082  // may get mapped to
11083  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
11084  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
11085                      (!cast<Instruction>(NAME # Type # "_POST")
11086                         GPR64sp:$Rn,
11087                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11088                         idxtype:$idx,
11089                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
11090}
11091
11092multiclass SIMDLdSt1SingleAliases<string asm> {
11093  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
11094  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
11095  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
11096  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
11097}
11098
11099multiclass SIMDLdSt2SingleAliases<string asm> {
11100  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
11101  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
11102  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
11103  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
11104}
11105
11106multiclass SIMDLdSt3SingleAliases<string asm> {
11107  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
11108  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
11109  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
11110  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
11111}
11112
11113multiclass SIMDLdSt4SingleAliases<string asm> {
11114  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
11115  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
11116  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
11117  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
11118}
11119} // end of 'let Predicates = [HasNEON]'
11120
11121//----------------------------------------------------------------------------
11122// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
11123//----------------------------------------------------------------------------
11124
11125let Predicates = [HasNEON, HasRDM] in {
11126
11127class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
11128                                    RegisterOperand regtype, string asm,
11129                                    string kind, list<dag> pattern>
11130  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
11131                                pattern> {
11132}
11133multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
11134                                             SDPatternOperator op> {
11135  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
11136    [(set (v4i16 V64:$dst),
11137          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
11138  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
11139    [(set (v8i16 V128:$dst),
11140          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
11141  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
11142    [(set (v2i32 V64:$dst),
11143          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
11144  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
11145    [(set (v4i32 V128:$dst),
11146          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
11147}
11148
11149multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
11150                                     SDPatternOperator op> {
11151  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
11152                                          V64, V64, V128_lo, VectorIndexH,
11153                                          asm, ".4h", ".4h", ".4h", ".h",
11154    [(set (v4i16 V64:$dst),
11155          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
11156                     (dup_v8i16 (v8i16 V128_lo:$Rm),
11157                                 VectorIndexH:$idx))))]> {
11158    bits<3> idx;
11159    let Inst{11} = idx{2};
11160    let Inst{21} = idx{1};
11161    let Inst{20} = idx{0};
11162  }
11163
11164  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
11165                                          V128, V128, V128_lo, VectorIndexH,
11166                                          asm, ".8h", ".8h", ".8h", ".h",
11167    [(set (v8i16 V128:$dst),
11168          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
11169                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
11170                                              VectorIndexH:$idx)))))]> {
11171    bits<3> idx;
11172    let Inst{11} = idx{2};
11173    let Inst{21} = idx{1};
11174    let Inst{20} = idx{0};
11175  }
11176
11177  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
11178                                          V64, V64, V128, VectorIndexS,
11179                                          asm, ".2s", ".2s", ".2s", ".s",
11180    [(set (v2i32 V64:$dst),
11181          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
11182                     (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
11183    bits<2> idx;
11184    let Inst{11} = idx{1};
11185    let Inst{21} = idx{0};
11186  }
11187
11188  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
11189                                          V128, V128, V128, VectorIndexS,
11190                                          asm, ".4s", ".4s", ".4s", ".s",
11191    [(set (v4i32 V128:$dst),
11192          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11193                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
11194                                              VectorIndexS:$idx)))))]> {
11195    bits<2> idx;
11196    let Inst{11} = idx{1};
11197    let Inst{21} = idx{0};
11198  }
11199
11200  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
11201                                          FPR16Op, FPR16Op, V128_lo,
11202                                          VectorIndexH, asm, ".h", "", "", ".h",
11203                                          []> {
11204    bits<3> idx;
11205    let Inst{11} = idx{2};
11206    let Inst{21} = idx{1};
11207    let Inst{20} = idx{0};
11208  }
11209
11210  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
11211                                          FPR32Op, FPR32Op, V128, VectorIndexS,
11212                                          asm, ".s", "", "", ".s",
11213    [(set (i32 FPR32Op:$dst),
11214          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
11215                   (i32 (vector_extract (v4i32 V128:$Rm),
11216                                        VectorIndexS:$idx)))))]> {
11217    bits<2> idx;
11218    let Inst{11} = idx{1};
11219    let Inst{21} = idx{0};
11220  }
11221}
11222} // let Predicates = [HasNeon, HasRDM]
11223
11224//----------------------------------------------------------------------------
11225// ARMv8.3 Complex ADD/MLA instructions
11226//----------------------------------------------------------------------------
11227
11228class ComplexRotationOperand<int Angle, int Remainder, string Type>
11229  : AsmOperandClass {
11230  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
11231  let DiagnosticType = "InvalidComplexRotation" # Type;
11232  let Name = "ComplexRotation" # Type;
11233}
11234def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11235                                                  SDNodeXForm<imm, [{
11236  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
11237}]>> {
11238  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
11239  let PrintMethod = "printComplexRotationOp<90, 0>";
11240}
11241def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11242                                                  SDNodeXForm<imm, [{
11243  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
11244}]>> {
11245  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
11246  let PrintMethod = "printComplexRotationOp<180, 90>";
11247}
11248let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11249class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
11250                                     RegisterOperand regtype, Operand rottype,
11251                                     string asm, string kind, list<dag> pattern>
11252  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11253      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11254      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
11255    Sched<[!if(Q, WriteVq, WriteVd)]> {
11256  bits<5> Rd;
11257  bits<5> Rn;
11258  bits<5> Rm;
11259  bits<1> rot;
11260  let Inst{31}    = 0;
11261  let Inst{30}    = Q;
11262  let Inst{29}    = U;
11263  let Inst{28-24} = 0b01110;
11264  let Inst{23-22} = size;
11265  let Inst{21}    = 0;
11266  let Inst{20-16} = Rm;
11267  let Inst{15-13} = opcode;
11268  // Non-tied version (FCADD) only has one rotation bit
11269  let Inst{12}    = rot;
11270  let Inst{11}    = 0;
11271  let Inst{10}    = 1;
11272  let Inst{9-5}   = Rn;
11273  let Inst{4-0}   = Rd;
11274}
11275
11276//8.3 CompNum - Floating-point complex number support
11277multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
11278                                          string asm, SDPatternOperator OpNode>{
11279  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11280  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
11281              asm, ".4h",
11282              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11283                                              (v4f16 V64:$Rn),
11284                                              (v4f16 V64:$Rm),
11285                                              (i32 rottype:$rot)))]>;
11286
11287  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
11288              asm, ".8h",
11289              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11290                                               (v8f16 V128:$Rn),
11291                                               (v8f16 V128:$Rm),
11292                                               (i32 rottype:$rot)))]>;
11293  }
11294
11295  let Predicates = [HasComplxNum, HasNEON] in {
11296  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
11297              asm, ".2s",
11298              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11299                                              (v2f32 V64:$Rn),
11300                                              (v2f32 V64:$Rm),
11301                                              (i32 rottype:$rot)))]>;
11302
11303  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
11304              asm, ".4s",
11305              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11306                                               (v4f32 V128:$Rn),
11307                                               (v4f32 V128:$Rm),
11308                                               (i32 rottype:$rot)))]>;
11309
11310  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
11311              asm, ".2d",
11312              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11313                                               (v2f64 V128:$Rn),
11314                                               (v2f64 V128:$Rm),
11315                                               (i32 rottype:$rot)))]>;
11316  }
11317}
11318
11319let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11320class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
11321                                         bits<3> opcode,
11322                                         RegisterOperand regtype,
11323                                         Operand rottype, string asm,
11324                                         string kind, list<dag> pattern>
11325  : I<(outs regtype:$dst),
11326      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11327      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11328      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
11329    Sched<[!if(Q, WriteVq, WriteVd)]> {
11330  bits<5> Rd;
11331  bits<5> Rn;
11332  bits<5> Rm;
11333  bits<2> rot;
11334  let Inst{31}    = 0;
11335  let Inst{30}    = Q;
11336  let Inst{29}    = U;
11337  let Inst{28-24} = 0b01110;
11338  let Inst{23-22} = size;
11339  let Inst{21}    = 0;
11340  let Inst{20-16} = Rm;
11341  let Inst{15-13} = opcode;
11342  let Inst{12-11} = rot;
11343  let Inst{10}    = 1;
11344  let Inst{9-5}   = Rn;
11345  let Inst{4-0}   = Rd;
11346}
11347
11348multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
11349                                             Operand rottype, string asm,
11350                                             SDPatternOperator OpNode> {
11351  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11352  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
11353              rottype, asm, ".4h",
11354              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11355                                              (v4f16 V64:$Rn),
11356                                              (v4f16 V64:$Rm),
11357                                              (i32 rottype:$rot)))]>;
11358
11359  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
11360              rottype, asm, ".8h",
11361              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11362                                               (v8f16 V128:$Rn),
11363                                               (v8f16 V128:$Rm),
11364                                               (i32 rottype:$rot)))]>;
11365  }
11366
11367  let Predicates = [HasComplxNum, HasNEON] in {
11368  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
11369              rottype, asm, ".2s",
11370              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11371                                              (v2f32 V64:$Rn),
11372                                              (v2f32 V64:$Rm),
11373                                              (i32 rottype:$rot)))]>;
11374
11375  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
11376              rottype, asm, ".4s",
11377              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11378                                               (v4f32 V128:$Rn),
11379                                               (v4f32 V128:$Rm),
11380                                               (i32 rottype:$rot)))]>;
11381
11382  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
11383              rottype, asm, ".2d",
11384              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11385                                               (v2f64 V128:$Rn),
11386                                               (v2f64 V128:$Rm),
11387                                               (i32 rottype:$rot)))]>;
11388  }
11389}
11390
11391let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11392class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
11393                                 bit opc1, bit opc2, RegisterOperand dst_reg,
11394                                 RegisterOperand lhs_reg,
11395                                 RegisterOperand rhs_reg, Operand vec_idx,
11396                                 Operand rottype, string asm, string apple_kind,
11397                                 string dst_kind, string lhs_kind,
11398                                 string rhs_kind, list<dag> pattern>
11399  : I<(outs dst_reg:$dst),
11400      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
11401      asm,
11402      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
11403      "$idx, $rot" # "|" # apple_kind #
11404      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
11405    Sched<[!if(Q, WriteVq, WriteVd)]> {
11406  bits<5> Rd;
11407  bits<5> Rn;
11408  bits<5> Rm;
11409  bits<2> rot;
11410
11411  let Inst{31}    = 0;
11412  let Inst{30}    = Q;
11413  let Inst{29}    = U;
11414  let Inst{28}    = Scalar;
11415  let Inst{27-24} = 0b1111;
11416  let Inst{23-22} = size;
11417  // Bit 21 must be set by the derived class.
11418  let Inst{20-16} = Rm;
11419  let Inst{15}    = opc1;
11420  let Inst{14-13} = rot;
11421  let Inst{12}    = opc2;
11422  // Bit 11 must be set by the derived class.
11423  let Inst{10}    = 0;
11424  let Inst{9-5}   = Rn;
11425  let Inst{4-0}   = Rd;
11426}
11427
11428// The complex instructions index by pairs of elements, so the VectorIndexes
11429// don't match the lane types, and the index bits are different to the other
11430// classes.
11431multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
11432                                     string asm> {
11433  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11434  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
11435                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
11436                      ".4h", ".h", []> {
11437    bits<1> idx;
11438    let Inst{11} = 0;
11439    let Inst{21} = idx{0};
11440  }
11441
11442  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
11443                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
11444                      ".8h", ".8h", ".h", []> {
11445    bits<2> idx;
11446    let Inst{11} = idx{1};
11447    let Inst{21} = idx{0};
11448  }
11449  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
11450
11451  let Predicates = [HasComplxNum, HasNEON] in {
11452  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
11453                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
11454                      ".4s", ".4s", ".s", []> {
11455    bits<1> idx;
11456    let Inst{11} = idx{0};
11457    let Inst{21} = 0;
11458  }
11459  } // Predicates = [HasComplxNum, HasNEON]
11460}
11461
11462//----------------------------------------------------------------------------
11463// Crypto extensions
11464//----------------------------------------------------------------------------
11465
11466let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11467class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
11468              list<dag> pat>
11469  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
11470    Sched<[WriteVq]>{
11471  bits<5> Rd;
11472  bits<5> Rn;
11473  let Inst{31-16} = 0b0100111000101000;
11474  let Inst{15-12} = opc;
11475  let Inst{11-10} = 0b10;
11476  let Inst{9-5}   = Rn;
11477  let Inst{4-0}   = Rd;
11478}
11479
11480class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
11481  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
11482            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
11483
11484class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
11485  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
11486            "$Rd = $dst",
11487            [(set (v16i8 V128:$dst),
11488                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
11489
11490let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11491class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
11492                     dag oops, dag iops, list<dag> pat>
11493  : I<oops, iops, asm,
11494      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
11495      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
11496    Sched<[WriteVq]>{
11497  bits<5> Rd;
11498  bits<5> Rn;
11499  bits<5> Rm;
11500  let Inst{31-21} = 0b01011110000;
11501  let Inst{20-16} = Rm;
11502  let Inst{15}    = 0;
11503  let Inst{14-12} = opc;
11504  let Inst{11-10} = 0b00;
11505  let Inst{9-5}   = Rn;
11506  let Inst{4-0}   = Rd;
11507}
11508
11509class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11510  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11511                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11512                   [(set (v4i32 FPR128:$dst),
11513                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11514                                 (v4i32 V128:$Rm)))]>;
11515
11516class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11517  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11518                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11519                   [(set (v4i32 V128:$dst),
11520                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11521                                 (v4i32 V128:$Rm)))]>;
11522
11523class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11524  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11525                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11526                   [(set (v4i32 FPR128:$dst),
11527                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11528                                 (v4i32 V128:$Rm)))]>;
11529
11530let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11531class SHA2OpInst<bits<4> opc, string asm, string kind,
11532                 string cstr, dag oops, dag iops,
11533                 list<dag> pat>
11534  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11535                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11536    Sched<[WriteVq]>{
11537  bits<5> Rd;
11538  bits<5> Rn;
11539  let Inst{31-16} = 0b0101111000101000;
11540  let Inst{15-12} = opc;
11541  let Inst{11-10} = 0b10;
11542  let Inst{9-5}   = Rn;
11543  let Inst{4-0}   = Rd;
11544}
11545
11546class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11547  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11548               (ins V128:$Rd, V128:$Rn),
11549               [(set (v4i32 V128:$dst),
11550                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11551
11552class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11553  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11554               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11555
11556// Armv8.2-A Crypto extensions
11557class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11558                    list<dag> pattern>
11559  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11560  bits<5> Vd;
11561  bits<5> Vn;
11562  let Inst{31-25} = 0b1100111;
11563  let Inst{9-5}   = Vn;
11564  let Inst{4-0}   = Vd;
11565}
11566
11567class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11568  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11569                  "$Vd = $Vdst", []> {
11570  let Inst{31-25} = 0b1100111;
11571  let Inst{24-21} = 0b0110;
11572  let Inst{20-15} = 0b000001;
11573  let Inst{14}    = op0;
11574  let Inst{13-12} = 0b00;
11575  let Inst{11-10} = op1;
11576}
11577class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11578  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11579class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11580  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11581
11582class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11583                string asmops, string cst>
11584  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11585  bits<5> Vm;
11586  let Inst{24-21} = 0b0011;
11587  let Inst{20-16} = Vm;
11588  let Inst{15}    = 0b1;
11589  let Inst{14}    = op0;
11590  let Inst{13-12} = 0b00;
11591  let Inst{11-10} = op1;
11592}
11593class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11594  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11595              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11596class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11597  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11598              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11599class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11600  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11601              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11602class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11603  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11604              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11605class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11606  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11607              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11608
11609class CryptoRRRR<bits<2>op0, string asm, string asmops>
11610  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11611                  asmops, "", []> {
11612  bits<5> Vm;
11613  bits<5> Va;
11614  let Inst{24-23} = 0b00;
11615  let Inst{22-21} = op0;
11616  let Inst{20-16} = Vm;
11617  let Inst{15}    = 0b0;
11618  let Inst{14-10} = Va;
11619}
11620class CryptoRRRR_16B<bits<2>op0, string asm>
11621 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11622                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11623}
11624class CryptoRRRR_4S<bits<2>op0, string asm>
11625 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11626                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11627}
11628
11629class CryptoRRRi6<string asm>
11630  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11631                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11632                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11633  bits<6> imm;
11634  bits<5> Vm;
11635  let Inst{24-21} = 0b0100;
11636  let Inst{20-16} = Vm;
11637  let Inst{15-10} = imm;
11638  let Inst{9-5}   = Vn;
11639  let Inst{4-0}   = Vd;
11640}
11641
11642class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11643  : BaseCryptoV82<(outs V128:$Vdst),
11644                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11645                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11646                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11647  bits<2> imm;
11648  bits<5> Vm;
11649  let Inst{24-21} = 0b0010;
11650  let Inst{20-16} = Vm;
11651  let Inst{15}    = 0b1;
11652  let Inst{14}    = op0;
11653  let Inst{13-12} = imm;
11654  let Inst{11-10} = op1;
11655}
11656
11657//----------------------------------------------------------------------------
11658// v8.1 atomic instructions extension:
11659// * CAS
11660// * CASP
11661// * SWP
11662// * LDOPregister<OP>, and aliases STOPregister<OP>
11663
11664// Instruction encodings:
11665//
11666//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11667// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11668// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11669// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11670// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11671// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11672
11673// Instruction syntax:
11674//
11675// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11676// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11677// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11678// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11679// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11680// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11681// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11682// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11683// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11684// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11685
11686let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11687class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11688                      string cstr, list<dag> pattern>
11689      : I<oops, iops, asm, operands, cstr, pattern> {
11690  bits<2> Sz;
11691  bit NP;
11692  bit Acq;
11693  bit Rel;
11694  bits<5> Rs;
11695  bits<5> Rn;
11696  bits<5> Rt;
11697  let Inst{31-30} = Sz;
11698  let Inst{29-24} = 0b001000;
11699  let Inst{23} = NP;
11700  let Inst{22} = Acq;
11701  let Inst{21} = 0b1;
11702  let Inst{20-16} = Rs;
11703  let Inst{15} = Rel;
11704  let Inst{14-10} = 0b11111;
11705  let Inst{9-5} = Rn;
11706  let Inst{4-0} = Rt;
11707  let Predicates = [HasLSE];
11708}
11709
11710class BaseCAS<string order, string size, RegisterClass RC>
11711      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11712                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11713                        "$out = $Rs",[]>,
11714        Sched<[WriteAtomic]> {
11715  let NP = 1;
11716}
11717
11718multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11719  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11720  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11721  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11722  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11723}
11724
11725class BaseCASP<string order, string size, RegisterOperand RC>
11726      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11727                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11728                        "$out = $Rs",[]>,
11729        Sched<[WriteAtomic]> {
11730  let NP = 0;
11731}
11732
11733multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11734  let Sz = 0b00, Acq = Acq, Rel = Rel in
11735    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11736  let Sz = 0b01, Acq = Acq, Rel = Rel in
11737    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11738}
11739
11740let Predicates = [HasLSE] in
11741class BaseSWP<string order, string size, RegisterClass RC>
11742      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11743          "\t$Rs, $Rt, [$Rn]","",[]>,
11744        Sched<[WriteAtomic]> {
11745  bits<2> Sz;
11746  bit Acq;
11747  bit Rel;
11748  bits<5> Rs;
11749  bits<3> opc = 0b000;
11750  bits<5> Rn;
11751  bits<5> Rt;
11752  let Inst{31-30} = Sz;
11753  let Inst{29-24} = 0b111000;
11754  let Inst{23} = Acq;
11755  let Inst{22} = Rel;
11756  let Inst{21} = 0b1;
11757  let Inst{20-16} = Rs;
11758  let Inst{15} = 0b1;
11759  let Inst{14-12} = opc;
11760  let Inst{11-10} = 0b00;
11761  let Inst{9-5} = Rn;
11762  let Inst{4-0} = Rt;
11763  let Predicates = [HasLSE];
11764}
11765
11766multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11767  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11768  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11769  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11770  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11771}
11772
11773let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11774class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11775      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11776          "\t$Rs, $Rt, [$Rn]","",[]>,
11777        Sched<[WriteAtomic]> {
11778  bits<2> Sz;
11779  bit Acq;
11780  bit Rel;
11781  bits<5> Rs;
11782  bits<3> opc;
11783  bits<5> Rn;
11784  bits<5> Rt;
11785  let Inst{31-30} = Sz;
11786  let Inst{29-24} = 0b111000;
11787  let Inst{23} = Acq;
11788  let Inst{22} = Rel;
11789  let Inst{21} = 0b1;
11790  let Inst{20-16} = Rs;
11791  let Inst{15} = 0b0;
11792  let Inst{14-12} = opc;
11793  let Inst{11-10} = 0b00;
11794  let Inst{9-5} = Rn;
11795  let Inst{4-0} = Rt;
11796  let Predicates = [HasLSE];
11797}
11798
11799multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11800                        string order> {
11801  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11802    def B : BaseLDOPregister<op, order, "b", GPR32>;
11803  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11804    def H : BaseLDOPregister<op, order, "h", GPR32>;
11805  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11806    def W : BaseLDOPregister<op, order, "", GPR32>;
11807  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11808    def X : BaseLDOPregister<op, order, "", GPR64>;
11809}
11810
11811// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11812// complex DAG for DstRHS.
11813let Predicates = [HasLSE] in
11814multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11815                                         string size, dag SrcRHS, dag DstRHS> {
11816  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11817            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11818  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11819            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11820  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11821            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11822  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11823            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11824  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11825            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11826}
11827
11828multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11829                                     string size, dag RHS> {
11830  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11831}
11832
11833multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11834                                         string size, dag LHS, dag RHS> {
11835  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11836}
11837
11838multiclass LDOPregister_patterns<string inst, string op> {
11839  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11840  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11841  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11842  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11843}
11844
11845multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11846  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11847                        (i64 GPR64:$Rm),
11848                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11849  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11850                        (i32 GPR32:$Rm),
11851                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11852  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11853                        (i32 GPR32:$Rm),
11854                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11855  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11856                        (i32 GPR32:$Rm),
11857                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11858}
11859
11860let Predicates = [HasLSE] in
11861multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11862                                        string size, dag OLD, dag NEW> {
11863  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11864            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11865  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11866            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11867  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11868            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11869  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11870            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11871  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11872            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11873}
11874
11875multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11876                                    string size, dag OLD, dag NEW> {
11877  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11878}
11879
11880multiclass CASregister_patterns<string inst, string op> {
11881  defm : CASregister_patterns_ord<inst, "X", op, "64",
11882                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11883  defm : CASregister_patterns_ord<inst, "W", op, "32",
11884                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11885  defm : CASregister_patterns_ord<inst, "H", op, "16",
11886                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11887  defm : CASregister_patterns_ord<inst, "B", op, "8",
11888                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11889}
11890
11891let Predicates = [HasLSE] in
11892class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11893                        Instruction inst> :
11894      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11895
11896multiclass STOPregister<string asm, string instr> {
11897  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11898                    !cast<Instruction>(instr # "LB")>;
11899  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11900                    !cast<Instruction>(instr # "LH")>;
11901  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11902                    !cast<Instruction>(instr # "LW")>;
11903  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11904                    !cast<Instruction>(instr # "LX")>;
11905  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11906                    !cast<Instruction>(instr # "B")>;
11907  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11908                    !cast<Instruction>(instr # "H")>;
11909  def : BaseSTOPregister<asm,        GPR32, WZR,
11910                    !cast<Instruction>(instr # "W")>;
11911  def : BaseSTOPregister<asm,        GPR64, XZR,
11912                    !cast<Instruction>(instr # "X")>;
11913}
11914
11915class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11916                        dag iops, dag oops, list<dag> pat>
11917    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11918      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11919  bits<5> Rt;
11920  bits<5> Rn;
11921  let Inst{31-21} = 0b11111000001;
11922  let Inst{15}    = 1;
11923  let Inst{14-12} = opc;
11924  let Inst{11-10} = 0b00;
11925  let Inst{9-5}   = Rn;
11926  let Inst{4-0}   = Rt;
11927
11928  let Predicates = [HasV8_7a];
11929}
11930
11931class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11932                      list<dag> pat = []>
11933    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11934  let Inst{20-16} = 0b11111;
11935}
11936
11937class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11938    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11939                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11940  bits<5> Rs;
11941  let Inst{20-16} = Rs;
11942}
11943
11944class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11945                             bits<2> op2, string asm>
11946  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11947      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11948      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11949      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11950    Sched<[]> {
11951  bits<5> Rd;
11952  bits<5> Rs;
11953  bits<5> Rn;
11954  let Inst{31-27} = 0b00011;
11955  let Inst{26} = isMove;
11956  let Inst{25-24} = 0b01;
11957  let Inst{23-22} = opcode;
11958  let Inst{21} = 0b0;
11959  let Inst{20-16} = Rs;
11960  let Inst{15-14} = op2;
11961  let Inst{13-12} = op1;
11962  let Inst{11-10} = 0b01;
11963  let Inst{9-5} = Rn;
11964  let Inst{4-0} = Rd;
11965
11966  let DecoderMethod = "DecodeCPYMemOpInstruction";
11967  let mayLoad = 1;
11968  let mayStore = 1;
11969}
11970
11971class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11972  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11973
11974class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11975  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11976
11977class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11978                        string asm>
11979  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11980      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11981      asm, "\t[$Rd]!, $Rn!, $Rm",
11982      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11983    Sched<[]> {
11984  bits<5> Rd;
11985  bits<5> Rn;
11986  bits<5> Rm;
11987  let Inst{31-27} = 0b00011;
11988  let Inst{26} = isTagging;
11989  let Inst{25-21} = 0b01110;
11990  let Inst{20-16} = Rm;
11991  let Inst{15-14} = opcode;
11992  let Inst{13} = op2;
11993  let Inst{12} = op1;
11994  let Inst{11-10} = 0b01;
11995  let Inst{9-5} = Rn;
11996  let Inst{4-0} = Rd;
11997
11998  let DecoderMethod = "DecodeSETMemOpInstruction";
11999  let mayLoad = 0;
12000  let mayStore = 1;
12001}
12002
12003class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
12004  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
12005
12006class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
12007  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
12008
12009multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
12010  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
12011  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
12012  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
12013  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
12014  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
12015  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
12016  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
12017  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
12018  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
12019  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
12020  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
12021  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
12022  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
12023  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
12024  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
12025  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
12026}
12027
12028multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
12029  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
12030  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
12031  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
12032  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
12033  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
12034  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
12035  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
12036  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
12037  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
12038  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
12039  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
12040  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
12041  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
12042  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
12043  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
12044  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
12045}
12046
12047multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
12048  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
12049  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
12050  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
12051  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
12052}
12053
12054multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
12055  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
12056  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
12057  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
12058  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
12059}
12060
12061//----------------------------------------------------------------------------
12062// 2022 Armv8.9/Armv9.4 Extensions
12063//----------------------------------------------------------------------------
12064
12065//---
12066// 2022 Architecture Extensions: General Data Processing (FEAT_CSSC)
12067//---
12068
12069class BaseTwoOperandRegImm<bit sf, bit Op, bit S, bits<4> opc,
12070                           RegisterClass regtype, ImmLeaf immtype, string asm,
12071                           SDPatternOperator OpNode>
12072    : I<(outs regtype:$Rd), (ins regtype:$Rn, immtype:$imm),
12073        asm, "\t$Rd, $Rn, $imm", "",
12074        [(set regtype:$Rd, (OpNode regtype:$Rn, immtype:$imm))]> {
12075  bits<5> Rd;
12076  bits<5> Rn;
12077  bits<8> imm;
12078
12079  let Inst{31}    = sf;
12080  let Inst{30}    = Op;
12081  let Inst{29}    = S;
12082  let Inst{28-22} = 0b1000111;
12083  let Inst{21-18} = opc;
12084  let Inst{17-10} = imm;
12085  let Inst{9-5}   = Rn;
12086  let Inst{4-0}   = Rd;
12087}
12088
12089class BaseComparisonOpReg<bit size, bit isUnsigned, bit isMin,
12090                          RegisterClass regtype, string asm,
12091                          SDPatternOperator OpNode>
12092    : BaseTwoOperandRegReg<size, 0b0, {0,1,1,0,?,?}, regtype, asm, OpNode>,
12093      Sched<[WriteI]> {
12094  let Inst{11} = isMin;
12095  let Inst{10} = isUnsigned;
12096  let mayLoad  = 0;
12097  let mayStore = 0;
12098  let hasSideEffects = 0;
12099}
12100
12101class BaseComparisonOpImm<bit size, bit isUnsigned, bit isMin,
12102                          RegisterClass regtype, ImmLeaf immtype, string asm,
12103                          SDPatternOperator OpNode>
12104    : BaseTwoOperandRegImm<size, 0b0, 0b0, {0,0,?,?}, regtype, immtype, asm,
12105                           OpNode>,
12106      Sched<[]> {
12107  let Inst{19} = isMin;
12108  let Inst{18} = isUnsigned;
12109  let mayLoad  = 0;
12110  let mayStore = 0;
12111  let hasSideEffects = 0;
12112}
12113
12114multiclass ComparisonOp<bit isUnsigned, bit isMin, string asm,
12115                        SDPatternOperator OpNode = null_frag> {
12116  def Wrr : BaseComparisonOpReg<0b0, isUnsigned, isMin, GPR32, asm, OpNode>;
12117
12118  def Wri : BaseComparisonOpImm<0b0, isUnsigned, isMin, GPR32,
12119                                !cond(isUnsigned : uimm8_32b,
12120                                      !not(isUnsigned) : simm8_32b), asm, OpNode>;
12121
12122  def Xrr : BaseComparisonOpReg<0b1, isUnsigned, isMin, GPR64, asm, OpNode>;
12123
12124  def Xri : BaseComparisonOpImm<0b1, isUnsigned, isMin, GPR64,
12125                                !cond(isUnsigned : uimm8_64b,
12126                                      !not(isUnsigned) : simm8_64b), asm, OpNode>;
12127}
12128
12129//---
12130// RCPC instructions (FEAT_LRCPC3)
12131//---
12132
12133class BaseLRCPC3<bits<2> size, bit V, bits<2> opc, dag oops, dag iops,
12134                 string asm, string operands, string cstr = "">
12135      : I<oops, iops, asm, operands, cstr, []>,
12136        Sched<[WriteAtomic]> {
12137  bits<5> Rt;
12138  bits<5> Rn;
12139  let Inst{31-30}    = size;
12140  let Inst{29-24}    = {0,1,1,V,0,1};
12141  let Inst{23-22}    = opc;
12142  let Inst{21}       = 0b0;
12143  //  Inst{20-12}
12144  let Inst{11-10}    = 0b10;
12145  let Inst{9-5}      = Rn;
12146  let Inst{4-0}      = Rt;
12147
12148  let mayLoad = Inst{22};
12149  let mayStore = !not(Inst{22});
12150  let hasSideEffects = 0;
12151}
12152
12153class BaseLRCPC3IntegerLoadStorePair<bits<2> size, bits<2> opc, bits<4> opc2,
12154                                     dag oops, dag iops, string asm,
12155                                     string operands, string cstr>
12156      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12157  bits<5> Rt2;
12158  let Inst{20-16} = Rt2;
12159  let Inst{15-12} = opc2;
12160}
12161
12162class BaseLRCPC3IntegerLoadStore<bits<2> size, bits<2> opc, dag oops, dag iops,
12163                                 string asm, string operands, string cstr>
12164      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12165  let Inst{20-12} = 0b000000000; // imm9
12166}
12167
12168multiclass LRCPC3NEONLoadStoreUnscaledOffset<bits<2> size, bits<2> opc, RegisterClass regtype,
12169                                             dag oops, dag iops, string asm> {
12170  def i : BaseLRCPC3<size, /*V*/1, opc, oops, iops, asm, "\t$Rt, [$Rn{, $simm}]", /*cstr*/""> {
12171    bits<9> simm; // signed immediate encoded in imm9=Rt2:imm4
12172    let Inst{20-12} = simm;
12173  }
12174
12175  def a : InstAlias<asm # "\t$Rt, [$Rn]",
12176                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
12177}
12178
12179class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
12180      : BaseSIMDLdStSingle<L, /*R*/0b0, /*opcode*/0b100, asm,
12181                           "\t$Vt$Q, [$Rn]", cst, oops, iops, []>,
12182        Sched<[]> {
12183  bit Q;
12184  let Inst{31}       = 0;
12185  let Inst{30}       = Q;
12186  let Inst{23}       = 0;
12187  let Inst{20-16}    = 0b00001;
12188  let Inst{12}       = 0; // S
12189  let Inst{11-10}    = 0b01; // size
12190
12191  let mayLoad = L;
12192  let mayStore = !not(L);
12193  let hasSideEffects = 1;
12194}
12195
12196//---
12197// Instrumentation Extension (FEAT_ITE)
12198//---
12199
12200let Predicates = [HasITE] in
12201def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
12202  let Inst{20-19} = 0b01;
12203  let Inst{18-16} = 0b011;
12204  let Inst{15-12} = 0b0111;
12205  let Inst{11-8}  = 0b0010;
12206  let Inst{7-5}   = 0b111;
12207}
12208
12209// * RCWCAS family
12210// * RCW<OP> family
12211
12212//--------------------------------------------------------------------
12213// Read-Check-Write Compare And Swap family (RCWCAS[S|P|PS]?[A|L|AL]?)
12214
12215// Instruction encoding:
12216//
12217//          31 30|29  24|23|22|21|20 16|15|14 13|12 11 10|9 5|4 0
12218// RCWCAS    0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12219// RCWSCAS   0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12220// RCWCASP   0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12221// RCWSCASP  0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12222
12223// Instruction syntax:
12224//
12225// RCW[S]CAS{<order>}   <Xs>,           <Xt>,          [<Xn|SP>]
12226// RCW[S]CASP{<order>}  <Xs>, <X(s+1)>, <Xt>, <X(t+1)> [<Xn|SP>]
12227
12228class BaseRCWCASEncoding<dag oops, dag iops, string asm>
12229      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", "$out = $Rs", []>,
12230        Sched<[]> {
12231  bit Acq;
12232  bit Rel;
12233  bit SC;
12234  bit Pair;
12235  bits<5> Rs;
12236  bits<5> Rn;
12237  bits<5> Rt;
12238  let Inst{31} = 0b0;
12239  let Inst{30} = SC;
12240  let Inst{29-24} = 0b011001;
12241  let Inst{23} = Acq;
12242  let Inst{22} = Rel;
12243  let Inst{21} = 0b1;
12244  let Inst{20-16} = Rs;
12245  let Inst{15-13} = 0b000;
12246  let Inst{12-11} = 0b01;
12247  let Inst{10} = Pair;
12248  let Inst{9-5} = Rn;
12249  let Inst{4-0} = Rt;
12250  let mayLoad = 1;
12251  let mayStore = 1;
12252  let hasSideEffects = 1;
12253  let Defs = [NZCV];
12254}
12255
12256multiclass BaseRCWCAS<dag oops, dag iops, string prefix> {
12257  let Acq = 0b0, Rel = 0b0 in
12258    def "" : BaseRCWCASEncoding<oops, iops, prefix # "">;
12259  let Acq = 0b1, Rel = 0b0 in
12260    def A  : BaseRCWCASEncoding<oops, iops, prefix # "a">;
12261  let Acq = 0b0, Rel = 0b1 in
12262    def L  : BaseRCWCASEncoding<oops, iops, prefix # "l">;
12263  let Acq = 0b1, Rel = 0b1 in
12264    def AL : BaseRCWCASEncoding<oops, iops, prefix # "al">;
12265}
12266
12267multiclass ReadCheckWriteCompareAndSwap {
12268  let SC = 0b0, Pair = 0b0, Predicates = [HasTHE] in
12269    defm CAS  : BaseRCWCAS<(outs GPR64:$out),
12270                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwcas" >;
12271  let SC = 0b1, Pair = 0b0, Predicates = [HasTHE] in
12272    defm SCAS : BaseRCWCAS<(outs GPR64:$out),
12273                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwscas">;
12274  let SC = 0b0, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12275    defm CASP : BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12276                           (ins XSeqPairClassOperand:$Rs,
12277                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12278                           "rcwcasp">;
12279  let SC = 0b1, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12280    defm SCASP: BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12281                           (ins XSeqPairClassOperand:$Rs,
12282                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12283                           "rcwscasp">;
12284}
12285
12286//------------------------------------------------------------------
12287// Read-Check-Write <OP> family (RCW[CLR|SET|SWP][S|P|PS]?[A|L|AL]?)
12288
12289// Instruction encoding:
12290//
12291//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12292// RCWCLR    0  0|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12293// RCWSCLR   0  1|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12294// RCWSET    0  0|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12295// RCWSSET   0  1|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12296// RCWSWP    0  0|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12297// RCWSSWP   0  1|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12298
12299//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12300// RCWCLRP   0  0|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12301// RCWSCLRP  0  1|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12302// RCWSETP   0  0|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12303// RCWSSETP  0  1|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12304// RCWSWPP   0  0|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12305// RCWSSWPP  0  1|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12306
12307// Instruction syntax:
12308//
12309// RCW[S]<OP>{<order>}   <Xs>,  <Xt>, [<Xn|SP>]
12310// RCW[S]<OP>P{<order>}  <Xt1>, <Xt2>, [<Xn|SP>]
12311
12312class BaseRCWOPEncoding<string asm>
12313      : I<(outs GPR64:$Rt),(ins GPR64:$Rs, GPR64sp:$Rn), asm,
12314          "\t$Rs, $Rt, [$Rn]", "", []>,
12315        Sched<[]> {
12316  bit Acq;
12317  bit Rel;
12318  bit SC;
12319  bits<3> opc;
12320  bits<5> Rs;
12321  bits<5> Rn;
12322  bits<5> Rt;
12323  let Inst{31} = 0b0;
12324  let Inst{30} = SC;
12325  let Inst{29-24} = 0b111000;
12326  let Inst{23} = Acq;
12327  let Inst{22} = Rel;
12328  let Inst{21} = 0b1;
12329  let Inst{20-16} = Rs;
12330  let Inst{15} = 0b1;
12331  let Inst{14-12} = opc;
12332  let Inst{11-10} = 0b00;
12333  let Inst{9-5} = Rn;
12334  let Inst{4-0} = Rt;
12335  let mayLoad = 1;
12336  let mayStore = 1;
12337  let hasSideEffects = 1;
12338  let Defs = [NZCV];
12339  let Predicates = [HasTHE];
12340}
12341
12342class BaseRCWOPPEncoding<string asm>
12343      : I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12344          (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn), asm,
12345          "\t$Rt, $Rt2, [$Rn]", "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12346        Sched<[]> {
12347  bit Acq;
12348  bit Rel;
12349  bit SC;
12350  bits<3> opc;
12351  bits<5> Rt2;
12352  bits<5> Rn;
12353  bits<5> Rt;
12354  let Inst{31} = 0b0;
12355  let Inst{30} = SC;
12356  let Inst{29-24} = 0b011001;
12357  let Inst{23} = Acq;
12358  let Inst{22} = Rel;
12359  let Inst{21} = 0b1;
12360  let Inst{20-16} = Rt2;
12361  let Inst{15} = 0b1;
12362  let Inst{14-12} = opc;
12363  let Inst{11-10} = 0b00;
12364  let Inst{9-5} = Rn;
12365  let Inst{4-0} = Rt;
12366  let mayLoad = 1;
12367  let mayStore = 1;
12368  let hasSideEffects = 1;
12369  let Defs = [NZCV];
12370  let Predicates = [HasTHE, HasD128];
12371}
12372
12373multiclass BaseRCWOP<string prefix> {
12374  let Acq = 0b0, Rel = 0b0 in def "" : BaseRCWOPEncoding<prefix # "">;
12375  let Acq = 0b1, Rel = 0b0 in def A  : BaseRCWOPEncoding<prefix # "a">;
12376  let Acq = 0b0, Rel = 0b1 in def L  : BaseRCWOPEncoding<prefix # "l">;
12377  let Acq = 0b1, Rel = 0b1 in def AL : BaseRCWOPEncoding<prefix # "al">;
12378
12379  let Acq = 0b0, Rel = 0b0 in def P   : BaseRCWOPPEncoding<prefix # "p">;
12380  let Acq = 0b1, Rel = 0b0 in def PA  : BaseRCWOPPEncoding<prefix # "pa">;
12381  let Acq = 0b0, Rel = 0b1 in def PL  : BaseRCWOPPEncoding<prefix # "pl">;
12382  let Acq = 0b1, Rel = 0b1 in def PAL : BaseRCWOPPEncoding<prefix # "pal">;
12383}
12384
12385multiclass ReadCheckWriteOperation<bits<3> opc, string op> {
12386  let SC = 0b0, opc = opc in defm ""  : BaseRCWOP<"rcw" # ""  # op>;
12387  let SC = 0b1, opc = opc in defm S   : BaseRCWOP<"rcw" # "s" # op >;
12388}
12389
12390//---
12391// 128-bit atomic instructions (FEAT_LSE128)
12392//---
12393
12394let mayLoad = 1, mayStore = 1, hasSideEffects = 0 in
12395class LSE128Base<bits<3> op0, bits<2> AR, bit o3, string asm>
12396: I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12397    (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn),
12398    asm, "\t$Rt, $Rt2, [$Rn]",
12399    "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12400  Sched<[]> {
12401  bits<5> Rt;
12402  bits<5> Rt2;
12403  bits<5> Rn;
12404  let Inst{31-24} = 0b00011001;
12405  let Inst{23-22} = AR;
12406  let Inst{21} = 0b1;
12407  let Inst{20-16} = Rt2;
12408  let Inst{15} = o3;
12409  let Inst{14-12} = op0;
12410  let Inst{11-10} = 0b00;
12411  let Inst{9-5} = Rn;
12412  let Inst{4-0} = Rt;
12413}
12414
12415//---
12416// 128-bit System Instructions (FEAT_SYSINSTR128)
12417//---
12418
12419// Instruction encoding:
12420//
12421//          31          19|18 16|15 12|11 8|7 5|4 0
12422// SYSP      1101010101001|  op1|   Cn|  Cm|op2| Rt
12423
12424// Instruction syntax:
12425//
12426// SYSP #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>, <Xt+1>}
12427
12428class RtSystemI128<bit L, dag oops, dag iops, string asm, string operands, list<dag> pattern = []> :
12429  RtSystemI<L, oops, iops, asm, operands, pattern> {
12430  let Inst{22}    = 0b1; // override BaseSystemI
12431}
12432
12433class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inputs>
12434  : RtSystemI128<L, outputs, inputs, asm, operands> {
12435  bits<3> op1;
12436  bits<4> Cn;
12437  bits<4> Cm;
12438  bits<3> op2;
12439  let Inst{20-19} = 0b01;
12440  let Inst{18-16} = op1;
12441  let Inst{15-12} = Cn;
12442  let Inst{11-8}  = Cm;
12443  let Inst{7-5}   = op2;
12444}
12445class SystemPXtI<bit L, string asm> :
12446  BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
12447  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
12448
12449
12450//----------------------------------------------------------------------------
12451// Allow the size specifier tokens to be upper case, not just lower.
12452def : TokenAlias<".4B", ".4b">;  // Add dot product
12453def : TokenAlias<".8B", ".8b">;
12454def : TokenAlias<".4H", ".4h">;
12455def : TokenAlias<".2S", ".2s">;
12456def : TokenAlias<".1D", ".1d">;
12457def : TokenAlias<".16B", ".16b">;
12458def : TokenAlias<".8H", ".8h">;
12459def : TokenAlias<".4S", ".4s">;
12460def : TokenAlias<".2D", ".2d">;
12461def : TokenAlias<".1Q", ".1q">;
12462def : TokenAlias<".2H", ".2h">;
12463def : TokenAlias<".B", ".b">;
12464def : TokenAlias<".H", ".h">;
12465def : TokenAlias<".S", ".s">;
12466def : TokenAlias<".D", ".d">;
12467def : TokenAlias<".Q", ".q">;
12468