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 extract_high_v8f16 :
137    ComplexPattern<v4f16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
138def extract_high_v4f32 :
139    ComplexPattern<v2f32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
140
141def gi_extract_high_v8f16 :
142  GIComplexOperandMatcher<v4s16, "selectExtractHigh">,
143  GIComplexPatternEquiv<extract_high_v8f16>;
144def gi_extract_high_v4f32 :
145  GIComplexOperandMatcher<v2s32, "selectExtractHigh">,
146  GIComplexPatternEquiv<extract_high_v4f32>;
147
148def extract_high_dup_v8i16 :
149   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
150def extract_high_dup_v4i32 :
151   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
152
153def dup_v8i16 :
154    PatFrags<(ops node:$LHS, node:$RHS),
155             [(v4i16 (extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 0))),
156              (v4i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS))]>;
157def dup_v4i32 :
158    PatFrags<(ops node:$LHS, node:$RHS),
159             [(v2i32 (extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 0))),
160              (v2i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS))]>;
161def dup_v8f16 :
162    PatFrags<(ops node:$LHS, node:$RHS),
163             [(v4f16 (extract_subvector (v8f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS)), (i64 0))),
164              (v4f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS))]>;
165def dup_v4f32 :
166    PatFrags<(ops node:$LHS, node:$RHS),
167             [(v2f32 (extract_subvector (v4f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS)), (i64 0))),
168              (v2f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS))]>;
169
170//===----------------------------------------------------------------------===//
171// Asm Operand Classes.
172//
173
174// Shifter operand for arithmetic shifted encodings.
175def ShifterOperand : AsmOperandClass {
176  let Name = "Shifter";
177}
178
179// Shifter operand for mov immediate encodings.
180def MovImm32ShifterOperand : AsmOperandClass {
181  let SuperClasses = [ShifterOperand];
182  let Name = "MovImm32Shifter";
183  let RenderMethod = "addShifterOperands";
184  let DiagnosticType = "InvalidMovImm32Shift";
185}
186def MovImm64ShifterOperand : AsmOperandClass {
187  let SuperClasses = [ShifterOperand];
188  let Name = "MovImm64Shifter";
189  let RenderMethod = "addShifterOperands";
190  let DiagnosticType = "InvalidMovImm64Shift";
191}
192
193// Shifter operand for arithmetic register shifted encodings.
194class ArithmeticShifterOperand<int width> : AsmOperandClass {
195  let SuperClasses = [ShifterOperand];
196  let Name = "ArithmeticShifter" # width;
197  let PredicateMethod = "isArithmeticShifter<" # width # ">";
198  let RenderMethod = "addShifterOperands";
199  let DiagnosticType = "AddSubRegShift" # width;
200}
201
202def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
203def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
204
205// Shifter operand for logical register shifted encodings.
206class LogicalShifterOperand<int width> : AsmOperandClass {
207  let SuperClasses = [ShifterOperand];
208  let Name = "LogicalShifter" # width;
209  let PredicateMethod = "isLogicalShifter<" # width # ">";
210  let RenderMethod = "addShifterOperands";
211  let DiagnosticType = "AddSubRegShift" # width;
212}
213
214def LogicalShifterOperand32 : LogicalShifterOperand<32>;
215def LogicalShifterOperand64 : LogicalShifterOperand<64>;
216
217// Shifter operand for logical vector 128/64-bit shifted encodings.
218def LogicalVecShifterOperand : AsmOperandClass {
219  let SuperClasses = [ShifterOperand];
220  let Name = "LogicalVecShifter";
221  let RenderMethod = "addShifterOperands";
222}
223def LogicalVecHalfWordShifterOperand : AsmOperandClass {
224  let SuperClasses = [LogicalVecShifterOperand];
225  let Name = "LogicalVecHalfWordShifter";
226  let RenderMethod = "addShifterOperands";
227}
228
229// The "MSL" shifter on the vector MOVI instruction.
230def MoveVecShifterOperand : AsmOperandClass {
231  let SuperClasses = [ShifterOperand];
232  let Name = "MoveVecShifter";
233  let RenderMethod = "addShifterOperands";
234}
235
236// Extend operand for arithmetic encodings.
237def ExtendOperand : AsmOperandClass {
238  let Name = "Extend";
239  let DiagnosticType = "AddSubRegExtendLarge";
240}
241def ExtendOperand64 : AsmOperandClass {
242  let SuperClasses = [ExtendOperand];
243  let Name = "Extend64";
244  let DiagnosticType = "AddSubRegExtendSmall";
245}
246// 'extend' that's a lsl of a 64-bit register.
247def ExtendOperandLSL64 : AsmOperandClass {
248  let SuperClasses = [ExtendOperand];
249  let Name = "ExtendLSL64";
250  let RenderMethod = "addExtend64Operands";
251  let DiagnosticType = "AddSubRegExtendLarge";
252}
253
254// 8-bit floating-point immediate encodings.
255def FPImmOperand : AsmOperandClass {
256  let Name = "FPImm";
257  let ParserMethod = "tryParseFPImm<true>";
258  let DiagnosticType = "InvalidFPImm";
259}
260
261def CondCode : AsmOperandClass {
262  let Name = "CondCode";
263  let DiagnosticType = "InvalidCondCode";
264}
265
266// A 32-bit register pasrsed as 64-bit
267def GPR32as64Operand : AsmOperandClass {
268  let Name = "GPR32as64";
269  let ParserMethod =
270      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
271}
272def GPR32as64 : RegisterOperand<GPR32> {
273  let ParserMatchClass = GPR32as64Operand;
274}
275
276// A 64-bit register pasrsed as 32-bit
277def GPR64as32Operand : AsmOperandClass {
278  let Name = "GPR64as32";
279  let ParserMethod =
280      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
281}
282def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
283  let ParserMatchClass = GPR64as32Operand;
284}
285
286// 8-bit immediate for AdvSIMD where 64-bit values of the form:
287// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
288// are encoded as the eight bit value 'abcdefgh'.
289def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
290
291class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
292  let Name = "UImm" # Width # "s" # Scale;
293  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
294  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
295  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
296}
297
298class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
299  let Name = "SImm" # Width # "s" # Scale;
300  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
301  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
302  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
303}
304
305//===----------------------------------------------------------------------===//
306// Operand Definitions.
307//
308
309// ADR[P] instruction labels.
310def AdrpOperand : AsmOperandClass {
311  let Name = "AdrpLabel";
312  let ParserMethod = "tryParseAdrpLabel";
313  let DiagnosticType = "InvalidLabel";
314}
315def adrplabel : Operand<i64> {
316  let EncoderMethod = "getAdrLabelOpValue";
317  let PrintMethod = "printAdrAdrpLabel";
318  let ParserMatchClass = AdrpOperand;
319  let OperandType = "OPERAND_PCREL";
320}
321
322def AdrOperand : AsmOperandClass {
323  let Name = "AdrLabel";
324  let ParserMethod = "tryParseAdrLabel";
325  let DiagnosticType = "InvalidLabel";
326}
327def adrlabel : Operand<i64> {
328  let EncoderMethod = "getAdrLabelOpValue";
329  let PrintMethod = "printAdrAdrpLabel";
330  let ParserMatchClass = AdrOperand;
331  let OperandType = "OPERAND_PCREL";
332}
333
334class SImmOperand<int width> : AsmOperandClass {
335  let Name = "SImm" # width;
336  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
337  let RenderMethod = "addImmOperands";
338  let PredicateMethod = "isSImm<" # width # ">";
339}
340
341class AsmImmRange<int Low, int High> : AsmOperandClass {
342  let Name = "Imm" # Low # "_" # High;
343  let DiagnosticType = "InvalidImm" # Low # "_" # High;
344  let RenderMethod = "addImmOperands";
345  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
346}
347
348// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
349def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
350def simm10Scaled : Operand<i64> {
351  let ParserMatchClass = SImm10s8Operand;
352  let DecoderMethod = "DecodeSImm<10>";
353  let PrintMethod = "printImmScale<8>";
354}
355
356def simm9s16 : Operand<i64> {
357  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
358  let DecoderMethod = "DecodeSImm<9>";
359  let PrintMethod = "printImmScale<16>";
360}
361
362// uimm6 predicate - True if the immediate is in the range [0, 63].
363def UImm6Operand : AsmOperandClass {
364  let Name = "UImm6";
365  let DiagnosticType = "InvalidImm0_63";
366}
367
368def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
369  let ParserMatchClass = UImm6Operand;
370}
371
372def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
373  let ParserMatchClass = AsmImmRange<0, 65535>;
374}
375
376def SImm9Operand : SImmOperand<9>;
377def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
378  let ParserMatchClass = SImm9Operand;
379  let DecoderMethod = "DecodeSImm<9>";
380}
381
382// imm0_255 predicate - True if the immediate is in the range [0,255].
383def Imm0_255Operand : AsmImmRange<0,255>;
384
385def uimm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
386  let ParserMatchClass = Imm0_255Operand;
387}
388def uimm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
389  let ParserMatchClass = Imm0_255Operand;
390}
391
392def SImm8Operand : SImmOperand<8>;
393def simm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
394  let ParserMatchClass = SImm8Operand;
395  let DecoderMethod = "DecodeSImm<8>";
396}
397def simm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 128; }]> {
398  let ParserMatchClass = SImm8Operand;
399  let DecoderMethod = "DecodeSImm<8>";
400}
401
402def SImm6Operand : SImmOperand<6>;
403def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
404  let ParserMatchClass = SImm6Operand;
405  let DecoderMethod = "DecodeSImm<6>";
406}
407
408def SImm5Operand : SImmOperand<5>;
409def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
410  let ParserMatchClass = SImm5Operand;
411  let DecoderMethod = "DecodeSImm<5>";
412}
413
414def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
415  let ParserMatchClass = SImm5Operand;
416  let DecoderMethod = "DecodeSImm<5>";
417}
418
419def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
420  let ParserMatchClass = SImm5Operand;
421  let DecoderMethod = "DecodeSImm<5>";
422  let PrintMethod = "printSImm<8>";
423}
424
425def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
426  let ParserMatchClass = SImm5Operand;
427  let DecoderMethod = "DecodeSImm<5>";
428  let PrintMethod = "printSImm<16>";
429}
430
431// simm7sN predicate - True if the immediate is a multiple of N in the range
432// [-64 * N, 63 * N].
433
434def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
435def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
436def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
437
438def simm7s4 : Operand<i32> {
439  let ParserMatchClass = SImm7s4Operand;
440  let PrintMethod = "printImmScale<4>";
441}
442
443def simm7s8 : Operand<i32> {
444  let ParserMatchClass = SImm7s8Operand;
445  let PrintMethod = "printImmScale<8>";
446}
447
448def simm7s16 : Operand<i32> {
449  let ParserMatchClass = SImm7s16Operand;
450  let PrintMethod = "printImmScale<16>";
451}
452
453def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
454
455def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
456def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
457def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
458def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
459def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
460
461def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
462def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
463
464def UImmS1XForm : SDNodeXForm<imm, [{
465  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
466}]>;
467def UImmS2XForm : SDNodeXForm<imm, [{
468  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
469}]>;
470def UImmS4XForm : SDNodeXForm<imm, [{
471  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
472}]>;
473def UImmS8XForm : SDNodeXForm<imm, [{
474  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
475}]>;
476
477// uimm5sN predicate - True if the immediate is a multiple of N in the range
478// [0 * N, 32 * N].
479def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
480def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
481def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
482
483def uimm5s2 : Operand<i64>, ImmLeaf<i64,
484                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
485                UImmS2XForm> {
486  let ParserMatchClass = UImm5s2Operand;
487  let PrintMethod = "printImmScale<2>";
488}
489def uimm5s4 : Operand<i64>, ImmLeaf<i64,
490                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
491                UImmS4XForm> {
492  let ParserMatchClass = UImm5s4Operand;
493  let PrintMethod = "printImmScale<4>";
494}
495def uimm5s8 : Operand<i64>, ImmLeaf<i64,
496                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
497                UImmS8XForm> {
498  let ParserMatchClass = UImm5s8Operand;
499  let PrintMethod = "printImmScale<8>";
500}
501
502// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
503// instead of ImmLeaf (Constant)
504def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
505                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
506                UImmS2XForm> {
507  let ParserMatchClass = UImm5s2Operand;
508  let PrintMethod = "printImmScale<2>";
509}
510def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
511                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
512                UImmS4XForm> {
513  let ParserMatchClass = UImm5s4Operand;
514  let PrintMethod = "printImmScale<4>";
515}
516def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
517                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
518                UImmS8XForm> {
519  let ParserMatchClass = UImm5s8Operand;
520  let PrintMethod = "printImmScale<8>";
521}
522
523// uimm6sN predicate - True if the immediate is a multiple of N in the range
524// [0 * N, 64 * N].
525def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
526def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
527def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
528def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
529def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
530
531def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
532  let ParserMatchClass = UImm6s1Operand;
533}
534def uimm6s2 : Operand<i64>, ImmLeaf<i64,
535[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
536  let PrintMethod = "printImmScale<2>";
537  let ParserMatchClass = UImm6s2Operand;
538}
539def uimm6s4 : Operand<i64>, ImmLeaf<i64,
540[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
541  let PrintMethod = "printImmScale<4>";
542  let ParserMatchClass = UImm6s4Operand;
543}
544def uimm6s8 : Operand<i64>, ImmLeaf<i64,
545[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
546  let PrintMethod = "printImmScale<8>";
547  let ParserMatchClass = UImm6s8Operand;
548}
549def uimm6s16 : Operand<i64>, ImmLeaf<i64,
550[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
551  let PrintMethod = "printImmScale<16>";
552  let ParserMatchClass = UImm6s16Operand;
553}
554
555def SImmS2XForm : SDNodeXForm<imm, [{
556  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
557}]>;
558def SImmS3XForm : SDNodeXForm<imm, [{
559  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
560}]>;
561def SImmS4XForm : SDNodeXForm<imm, [{
562  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
563}]>;
564def SImmS16XForm : SDNodeXForm<imm, [{
565  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
566}]>;
567def SImmS32XForm : SDNodeXForm<imm, [{
568  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
569}]>;
570
571// simm6sN predicate - True if the immediate is a multiple of N in the range
572// [-32 * N, 31 * N].
573def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
574def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
575  let ParserMatchClass = SImm6s1Operand;
576  let DecoderMethod = "DecodeSImm<6>";
577}
578
579// simm4sN predicate - True if the immediate is a multiple of N in the range
580// [ -8* N, 7 * N].
581def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
582def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
583def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
584def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
585def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
586def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
587
588def simm4s1 : Operand<i64>, ImmLeaf<i64,
589[{ return Imm >=-8  && Imm <= 7; }]> {
590  let ParserMatchClass = SImm4s1Operand;
591  let DecoderMethod = "DecodeSImm<4>";
592}
593
594def simm4s2 : Operand<i64>, ImmLeaf<i64,
595[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
596  let PrintMethod = "printImmScale<2>";
597  let ParserMatchClass = SImm4s2Operand;
598  let DecoderMethod = "DecodeSImm<4>";
599}
600
601def simm4s3 : Operand<i64>, ImmLeaf<i64,
602[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
603  let PrintMethod = "printImmScale<3>";
604  let ParserMatchClass = SImm4s3Operand;
605  let DecoderMethod = "DecodeSImm<4>";
606}
607
608def simm4s4 : Operand<i64>, ImmLeaf<i64,
609[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
610  let PrintMethod = "printImmScale<4>";
611  let ParserMatchClass = SImm4s4Operand;
612  let DecoderMethod = "DecodeSImm<4>";
613}
614def simm4s16 : Operand<i64>, ImmLeaf<i64,
615[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
616  let PrintMethod = "printImmScale<16>";
617  let ParserMatchClass = SImm4s16Operand;
618  let DecoderMethod = "DecodeSImm<4>";
619}
620def simm4s32 : Operand<i64>, ImmLeaf<i64,
621[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
622  let PrintMethod = "printImmScale<32>";
623  let ParserMatchClass = SImm4s32Operand;
624  let DecoderMethod = "DecodeSImm<4>";
625}
626
627def Imm1_8Operand : AsmImmRange<1, 8>;
628def Imm1_16Operand : AsmImmRange<1, 16>;
629def Imm1_32Operand : AsmImmRange<1, 32>;
630def Imm1_64Operand : AsmImmRange<1, 64>;
631
632class BranchTarget<int N> : AsmOperandClass {
633  let Name = "BranchTarget" # N;
634  let DiagnosticType = "InvalidLabel";
635  let PredicateMethod = "isBranchTarget<" # N # ">";
636}
637
638class PCRelLabel<int N> : BranchTarget<N> {
639  let Name = "PCRelLabel" # N;
640}
641
642def BranchTarget14Operand : BranchTarget<14>;
643def BranchTarget26Operand : BranchTarget<26>;
644def PCRelLabel19Operand   : PCRelLabel<19>;
645
646def MovWSymbolG3AsmOperand : AsmOperandClass {
647  let Name = "MovWSymbolG3";
648  let RenderMethod = "addImmOperands";
649}
650
651def movw_symbol_g3 : Operand<i32> {
652  let ParserMatchClass = MovWSymbolG3AsmOperand;
653}
654
655def MovWSymbolG2AsmOperand : AsmOperandClass {
656  let Name = "MovWSymbolG2";
657  let RenderMethod = "addImmOperands";
658}
659
660def movw_symbol_g2 : Operand<i32> {
661  let ParserMatchClass = MovWSymbolG2AsmOperand;
662}
663
664def MovWSymbolG1AsmOperand : AsmOperandClass {
665  let Name = "MovWSymbolG1";
666  let RenderMethod = "addImmOperands";
667}
668
669def movw_symbol_g1 : Operand<i32> {
670  let ParserMatchClass = MovWSymbolG1AsmOperand;
671}
672
673def MovWSymbolG0AsmOperand : AsmOperandClass {
674  let Name = "MovWSymbolG0";
675  let RenderMethod = "addImmOperands";
676}
677
678def movw_symbol_g0 : Operand<i32> {
679  let ParserMatchClass = MovWSymbolG0AsmOperand;
680}
681
682class fixedpoint_i32<ValueType FloatVT>
683  : Operand<FloatVT>,
684    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
685  let EncoderMethod = "getFixedPointScaleOpValue";
686  let DecoderMethod = "DecodeFixedPointScaleImm32";
687  let ParserMatchClass = Imm1_32Operand;
688}
689
690class fixedpoint_i64<ValueType FloatVT>
691  : Operand<FloatVT>,
692    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
693  let EncoderMethod = "getFixedPointScaleOpValue";
694  let DecoderMethod = "DecodeFixedPointScaleImm64";
695  let ParserMatchClass = Imm1_64Operand;
696}
697
698def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
699def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
700def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
701
702def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
703def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
704def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
705
706def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
707  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
708}]> {
709  let EncoderMethod = "getVecShiftR8OpValue";
710  let DecoderMethod = "DecodeVecShiftR8Imm";
711  let ParserMatchClass = Imm1_8Operand;
712}
713def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
714  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
715}]> {
716  let EncoderMethod = "getVecShiftR16OpValue";
717  let DecoderMethod = "DecodeVecShiftR16Imm";
718  let ParserMatchClass = Imm1_16Operand;
719}
720def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
721  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
722}]> {
723  let EncoderMethod = "getVecShiftR16OpValue";
724  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
725  let ParserMatchClass = Imm1_8Operand;
726}
727def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
728  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
729}]> {
730  let EncoderMethod = "getVecShiftR32OpValue";
731  let DecoderMethod = "DecodeVecShiftR32Imm";
732  let ParserMatchClass = Imm1_32Operand;
733}
734def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
735  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
736}]> {
737  let EncoderMethod = "getVecShiftR32OpValue";
738  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
739  let ParserMatchClass = Imm1_16Operand;
740}
741def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
742  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
743}]> {
744  let EncoderMethod = "getVecShiftR64OpValue";
745  let DecoderMethod = "DecodeVecShiftR64Imm";
746  let ParserMatchClass = Imm1_64Operand;
747}
748def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
749  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
750}]> {
751  let EncoderMethod = "getVecShiftR64OpValue";
752  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
753  let ParserMatchClass = Imm1_32Operand;
754}
755
756// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
757// (ImmLeaf)
758def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
759  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
760}]> {
761  let EncoderMethod = "getVecShiftR8OpValue";
762  let DecoderMethod = "DecodeVecShiftR8Imm";
763  let ParserMatchClass = Imm1_8Operand;
764}
765def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
766  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
767}]> {
768  let EncoderMethod = "getVecShiftR16OpValue";
769  let DecoderMethod = "DecodeVecShiftR16Imm";
770  let ParserMatchClass = Imm1_16Operand;
771}
772def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
773  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
774}]> {
775  let EncoderMethod = "getVecShiftR32OpValue";
776  let DecoderMethod = "DecodeVecShiftR32Imm";
777  let ParserMatchClass = Imm1_32Operand;
778}
779def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
780  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
781}]> {
782  let EncoderMethod = "getVecShiftR64OpValue";
783  let DecoderMethod = "DecodeVecShiftR64Imm";
784  let ParserMatchClass = Imm1_64Operand;
785}
786
787def Imm0_0Operand : AsmImmRange<0, 0>;
788def Imm0_1Operand : AsmImmRange<0, 1>;
789def Imm0_3Operand : AsmImmRange<0, 3>;
790def Imm0_7Operand : AsmImmRange<0, 7>;
791def Imm0_15Operand : AsmImmRange<0, 15>;
792def Imm0_31Operand : AsmImmRange<0, 31>;
793def Imm0_63Operand : AsmImmRange<0, 63>;
794
795def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
796  return (((uint32_t)Imm) < 8);
797}]> {
798  let EncoderMethod = "getVecShiftL8OpValue";
799  let DecoderMethod = "DecodeVecShiftL8Imm";
800  let ParserMatchClass = Imm0_7Operand;
801}
802def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
803  return (((uint32_t)Imm) < 16);
804}]> {
805  let EncoderMethod = "getVecShiftL16OpValue";
806  let DecoderMethod = "DecodeVecShiftL16Imm";
807  let ParserMatchClass = Imm0_15Operand;
808}
809def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
810  return (((uint32_t)Imm) < 32);
811}]> {
812  let EncoderMethod = "getVecShiftL32OpValue";
813  let DecoderMethod = "DecodeVecShiftL32Imm";
814  let ParserMatchClass = Imm0_31Operand;
815}
816def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
817  return (((uint32_t)Imm) < 64);
818}]> {
819  let EncoderMethod = "getVecShiftL64OpValue";
820  let DecoderMethod = "DecodeVecShiftL64Imm";
821  let ParserMatchClass = Imm0_63Operand;
822}
823
824// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
825// (ImmLeaf)
826def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
827  return (((uint32_t)Imm) < 8);
828}]> {
829  let EncoderMethod = "getVecShiftL8OpValue";
830  let DecoderMethod = "DecodeVecShiftL8Imm";
831  let ParserMatchClass = Imm0_7Operand;
832}
833def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
834  return (((uint32_t)Imm) < 16);
835}]> {
836  let EncoderMethod = "getVecShiftL16OpValue";
837  let DecoderMethod = "DecodeVecShiftL16Imm";
838  let ParserMatchClass = Imm0_15Operand;
839}
840def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
841  return (((uint32_t)Imm) < 32);
842}]> {
843  let EncoderMethod = "getVecShiftL32OpValue";
844  let DecoderMethod = "DecodeVecShiftL32Imm";
845  let ParserMatchClass = Imm0_31Operand;
846}
847def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
848  return (((uint32_t)Imm) < 64);
849}]> {
850  let EncoderMethod = "getVecShiftL64OpValue";
851  let DecoderMethod = "DecodeVecShiftL64Imm";
852  let ParserMatchClass = Imm0_63Operand;
853}
854
855// Crazy immediate formats used by 32-bit and 64-bit logical immediate
856// instructions for splatting repeating bit patterns across the immediate.
857def logical_imm32_XFORM : SDNodeXForm<imm, [{
858  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
859  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
860}]>;
861def logical_imm64_XFORM : SDNodeXForm<imm, [{
862  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
863  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
864}]>;
865
866def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
867  GISDNodeXFormEquiv<logical_imm32_XFORM>;
868def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
869  GISDNodeXFormEquiv<logical_imm64_XFORM>;
870
871let DiagnosticType = "LogicalSecondSource" in {
872  def LogicalImm32Operand : AsmOperandClass {
873    let Name = "LogicalImm32";
874    let PredicateMethod = "isLogicalImm<int32_t>";
875    let RenderMethod = "addLogicalImmOperands<int32_t>";
876  }
877  def LogicalImm64Operand : AsmOperandClass {
878    let Name = "LogicalImm64";
879    let PredicateMethod = "isLogicalImm<int64_t>";
880    let RenderMethod = "addLogicalImmOperands<int64_t>";
881  }
882  def LogicalImm32NotOperand : AsmOperandClass {
883    let Name = "LogicalImm32Not";
884    let PredicateMethod = "isLogicalImm<int32_t>";
885    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
886  }
887  def LogicalImm64NotOperand : AsmOperandClass {
888    let Name = "LogicalImm64Not";
889    let PredicateMethod = "isLogicalImm<int64_t>";
890    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
891  }
892}
893
894def Imm0_127Operand : AsmImmRange<0, 127>;
895
896let OperandType = "OPERAND_IMMEDIATE" in {
897
898def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
899  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
900}], logical_imm32_XFORM> {
901  let PrintMethod = "printLogicalImm<int32_t>";
902  let ParserMatchClass = LogicalImm32Operand;
903}
904def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
905  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
906}], logical_imm64_XFORM> {
907  let PrintMethod = "printLogicalImm<int64_t>";
908  let ParserMatchClass = LogicalImm64Operand;
909}
910def logical_imm32_not : Operand<i32> {
911  let ParserMatchClass = LogicalImm32NotOperand;
912}
913def logical_imm64_not : Operand<i64> {
914  let ParserMatchClass = LogicalImm64NotOperand;
915}
916
917// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
918let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
919def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
920  return ((uint32_t)Imm) < 65536;
921}]>;
922
923def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
924  return ((uint64_t)Imm) < 65536;
925}]>;
926
927def imm64_0_65535 : Operand<i64>, ImmLeaf<i64, [{
928  return ((uint64_t)Imm) < 65536;
929}]>;
930} // ParserMatchClass
931
932def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
933  return ((uint32_t)Imm) < 256;
934}]> {
935  let ParserMatchClass = Imm0_255Operand;
936  let PrintMethod = "printImm";
937}
938
939// imm0_127 predicate - True if the immediate is in the range [0,127]
940def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
941  return ((uint32_t)Imm) < 128;
942}]> {
943  let ParserMatchClass = Imm0_127Operand;
944  let PrintMethod = "printImm";
945}
946
947def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
948  return ((uint64_t)Imm) < 128;
949}]> {
950  let ParserMatchClass = Imm0_127Operand;
951  let PrintMethod = "printImm";
952}
953
954// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
955// for all shift-amounts.
956
957// imm0_63 predicate - True if the immediate is in the range [0,63]
958def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
959  return ((uint64_t)Imm) < 64;
960}]> {
961  let ParserMatchClass = Imm0_63Operand;
962}
963
964def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
965  return ((uint64_t)Imm) < 64;
966}]> {
967  let ParserMatchClass = Imm0_63Operand;
968}
969
970// imm0_31 predicate - True if the immediate is in the range [0,31]
971def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
972  return ((uint64_t)Imm) < 32;
973}]> {
974  let ParserMatchClass = Imm0_31Operand;
975}
976
977// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
978// instead of Constant (ImmLeaf)
979def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
980  return ((uint64_t)Imm) < 32;
981}]> {
982  let ParserMatchClass = Imm0_31Operand;
983}
984
985// True if the 32-bit immediate is in the range [0,31]
986def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
987  return ((uint64_t)Imm) < 32;
988}]> {
989  let ParserMatchClass = Imm0_31Operand;
990}
991
992// imm0_1 predicate - True if the immediate is in the range [0,1]
993def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
994  return ((uint64_t)Imm) < 2;
995}]> {
996  let ParserMatchClass = Imm0_1Operand;
997}
998
999// timm0_1 - as above, but use TargetConstant (TImmLeaf)
1000def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
1001  return ((uint64_t)Imm) < 2;
1002}]> {
1003  let ParserMatchClass = Imm0_1Operand;
1004}
1005
1006// timm32_0_1 predicate - True if the 32-bit immediate is in the range [0,1]
1007def timm32_0_1 : Operand<i32>, TImmLeaf<i32, [{
1008  return ((uint32_t)Imm) < 2;
1009}]> {
1010  let ParserMatchClass = Imm0_1Operand;
1011}
1012
1013// imm0_15 predicate - True if the immediate is in the range [0,15]
1014def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
1015  return ((uint64_t)Imm) < 16;
1016}]> {
1017  let ParserMatchClass = Imm0_15Operand;
1018}
1019
1020// imm0_7 predicate - True if the immediate is in the range [0,7]
1021def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
1022  return ((uint64_t)Imm) < 8;
1023}]> {
1024  let ParserMatchClass = Imm0_7Operand;
1025}
1026
1027// imm0_3 predicate - True if the immediate is in the range [0,3]
1028def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
1029  return ((uint64_t)Imm) < 4;
1030}]> {
1031  let ParserMatchClass = Imm0_3Operand;
1032}
1033
1034// timm32_0_3 predicate - True if the 32-bit immediate is in the range [0,3]
1035def timm32_0_3 : Operand<i32>, TImmLeaf<i32, [{
1036  return ((uint32_t)Imm) < 4;
1037}]> {
1038  let ParserMatchClass = Imm0_3Operand;
1039}
1040
1041// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
1042def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
1043  return ((uint32_t)Imm) < 8;
1044}]> {
1045  let ParserMatchClass = Imm0_7Operand;
1046}
1047
1048// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1049def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
1050  return ((uint32_t)Imm) < 16;
1051}]> {
1052  let ParserMatchClass = Imm0_15Operand;
1053}
1054
1055// timm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1056def timm32_0_15 : Operand<i32>, TImmLeaf<i32, [{
1057  return ((uint32_t)Imm) < 16;
1058}]> {
1059  let ParserMatchClass = Imm0_15Operand;
1060}
1061
1062// timm32_0_31 predicate - True if the 32-bit immediate is in the range [0,31]
1063def timm32_0_31 : Operand<i32>, TImmLeaf<i32, [{
1064  return ((uint32_t)Imm) < 32;
1065}]> {
1066  let ParserMatchClass = Imm0_31Operand;
1067}
1068
1069// timm32_0_255 predicate - True if the 32-bit immediate is in the range [0,255]
1070def timm32_0_255 : Operand<i32>, TImmLeaf<i32, [{
1071  return ((uint32_t)Imm) < 256;
1072}]> {
1073  let ParserMatchClass = Imm0_255Operand;
1074}
1075
1076} // let OperandType = "OPERAND_IMMEDIATE"
1077
1078// An arithmetic shifter operand:
1079//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
1080//  {5-0} - imm6
1081class arith_shift<ValueType Ty, int width> : Operand<Ty> {
1082  let PrintMethod = "printShifter";
1083  let ParserMatchClass = !cast<AsmOperandClass>(
1084                         "ArithmeticShifterOperand" # width);
1085}
1086
1087def arith_shift32 : arith_shift<i32, 32>;
1088def arith_shift64 : arith_shift<i64, 64>;
1089
1090class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
1091    : Operand<Ty>,
1092      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
1093  let PrintMethod = "printShiftedRegister";
1094  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
1095}
1096
1097def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
1098def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
1099
1100def gi_arith_shifted_reg32 :
1101  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1102  GIComplexPatternEquiv<arith_shifted_reg32>;
1103
1104def gi_arith_shifted_reg64 :
1105  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1106  GIComplexPatternEquiv<arith_shifted_reg64>;
1107
1108// An arithmetic shifter operand:
1109//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1110//  {5-0} - imm6
1111class logical_shift<int width> : Operand<i32> {
1112  let PrintMethod = "printShifter";
1113  let ParserMatchClass = !cast<AsmOperandClass>(
1114                         "LogicalShifterOperand" # width);
1115}
1116
1117def logical_shift32 : logical_shift<32>;
1118def logical_shift64 : logical_shift<64>;
1119
1120class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1121    : Operand<Ty>,
1122      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1123  let PrintMethod = "printShiftedRegister";
1124  let MIOperandInfo = (ops regclass, shiftop);
1125}
1126
1127def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1128def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1129
1130def gi_logical_shifted_reg32 :
1131  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1132  GIComplexPatternEquiv<logical_shifted_reg32>;
1133
1134def gi_logical_shifted_reg64 :
1135  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1136  GIComplexPatternEquiv<logical_shifted_reg64>;
1137
1138// A logical vector shifter operand:
1139//  {7-6} - shift type: 00 = lsl
1140//  {5-0} - imm6: #0, #8, #16, or #24
1141def logical_vec_shift : Operand<i32> {
1142  let PrintMethod = "printShifter";
1143  let EncoderMethod = "getVecShifterOpValue";
1144  let ParserMatchClass = LogicalVecShifterOperand;
1145}
1146
1147// A logical vector half-word shifter operand:
1148//  {7-6} - shift type: 00 = lsl
1149//  {5-0} - imm6: #0 or #8
1150def logical_vec_hw_shift : Operand<i32> {
1151  let PrintMethod = "printShifter";
1152  let EncoderMethod = "getVecShifterOpValue";
1153  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1154}
1155
1156// A vector move shifter operand:
1157//  {0} - imm1: #8 or #16
1158def move_vec_shift : Operand<i32> {
1159  let PrintMethod = "printShifter";
1160  let EncoderMethod = "getMoveVecShifterOpValue";
1161  let ParserMatchClass = MoveVecShifterOperand;
1162}
1163
1164let DiagnosticType = "AddSubSecondSource" in {
1165  def AddSubImmOperand : AsmOperandClass {
1166    let Name = "AddSubImm";
1167    let ParserMethod = "tryParseImmWithOptionalShift";
1168    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1169  }
1170  def AddSubImmNegOperand : AsmOperandClass {
1171    let Name = "AddSubImmNeg";
1172    let ParserMethod = "tryParseImmWithOptionalShift";
1173    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1174  }
1175}
1176// An ADD/SUB immediate shifter operand:
1177//  second operand:
1178//  {7-6} - shift type: 00 = lsl
1179//  {5-0} - imm6: #0 or #12
1180class addsub_shifted_imm<ValueType Ty>
1181    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1182  let PrintMethod = "printAddSubImm";
1183  let EncoderMethod = "getAddSubImmOpValue";
1184  let ParserMatchClass = AddSubImmOperand;
1185  let MIOperandInfo = (ops i32imm, i32imm);
1186}
1187
1188class addsub_shifted_imm_neg<ValueType Ty>
1189    : Operand<Ty> {
1190  let EncoderMethod = "getAddSubImmOpValue";
1191  let ParserMatchClass = AddSubImmNegOperand;
1192  let MIOperandInfo = (ops i32imm, i32imm);
1193}
1194
1195def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1196def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1197def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1198def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1199
1200def gi_addsub_shifted_imm32 :
1201    GIComplexOperandMatcher<s32, "selectArithImmed">,
1202    GIComplexPatternEquiv<addsub_shifted_imm32>;
1203
1204def gi_addsub_shifted_imm64 :
1205    GIComplexOperandMatcher<s64, "selectArithImmed">,
1206    GIComplexPatternEquiv<addsub_shifted_imm64>;
1207
1208class neg_addsub_shifted_imm<ValueType Ty>
1209    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1210  let PrintMethod = "printAddSubImm";
1211  let EncoderMethod = "getAddSubImmOpValue";
1212  let ParserMatchClass = AddSubImmOperand;
1213  let MIOperandInfo = (ops i32imm, i32imm);
1214}
1215
1216def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1217def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1218
1219def gi_neg_addsub_shifted_imm32 :
1220    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1221    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1222
1223def gi_neg_addsub_shifted_imm64 :
1224    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1225    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1226
1227// An extend operand:
1228//  {5-3} - extend type
1229//  {2-0} - imm3
1230def arith_extend : Operand<i32> {
1231  let PrintMethod = "printArithExtend";
1232  let ParserMatchClass = ExtendOperand;
1233}
1234def arith_extend64 : Operand<i32> {
1235  let PrintMethod = "printArithExtend";
1236  let ParserMatchClass = ExtendOperand64;
1237}
1238
1239// 'extend' that's a lsl of a 64-bit register.
1240def arith_extendlsl64 : Operand<i32> {
1241  let PrintMethod = "printArithExtend";
1242  let ParserMatchClass = ExtendOperandLSL64;
1243}
1244
1245class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1246                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1247  let PrintMethod = "printExtendedRegister";
1248  let MIOperandInfo = (ops GPR32, arith_extend);
1249}
1250
1251class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1252                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1253  let PrintMethod = "printExtendedRegister";
1254  let MIOperandInfo = (ops GPR32, arith_extend64);
1255}
1256
1257def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1258def gi_arith_extended_reg32_i32 :
1259    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1260    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1261
1262def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1263def gi_arith_extended_reg32_i64 :
1264    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1265    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1266
1267def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1268def gi_arith_extended_reg32to64_i64 :
1269    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1270    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1271
1272def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
1273
1274// Floating-point immediate.
1275
1276def fpimm16XForm : SDNodeXForm<fpimm, [{
1277      APFloat InVal = N->getValueAPF();
1278      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1279      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1280    }]>;
1281
1282def fpimm32XForm : SDNodeXForm<fpimm, [{
1283      APFloat InVal = N->getValueAPF();
1284      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1285      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1286    }]>;
1287
1288def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1289      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1290                                                          .bitcastToAPInt()
1291                                                          .getZExtValue());
1292      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1293    }]>;
1294
1295def fpimm64XForm : SDNodeXForm<fpimm, [{
1296      APFloat InVal = N->getValueAPF();
1297      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1298      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1299    }]>;
1300
1301def fpimm16 : Operand<f16>,
1302              FPImmLeaf<f16, [{
1303      return AArch64_AM::getFP16Imm(Imm) != -1;
1304    }], fpimm16XForm> {
1305  let ParserMatchClass = FPImmOperand;
1306  let PrintMethod = "printFPImmOperand";
1307}
1308
1309def fpimmbf16 : Operand<bf16>,
1310                FPImmLeaf<bf16, [{
1311      return AArch64_AM::getFP16Imm(Imm) != -1;
1312    }], fpimm16XForm>;
1313
1314def fpimm32 : Operand<f32>,
1315              FPImmLeaf<f32, [{
1316      return AArch64_AM::getFP32Imm(Imm) != -1;
1317    }], fpimm32XForm> {
1318  let ParserMatchClass = FPImmOperand;
1319  let PrintMethod = "printFPImmOperand";
1320}
1321
1322def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1323      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1324      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1325    }], fpimm32SIMDModImmType4XForm> {
1326}
1327
1328def fpimm64 : Operand<f64>,
1329              FPImmLeaf<f64, [{
1330      return AArch64_AM::getFP64Imm(Imm) != -1;
1331    }], fpimm64XForm> {
1332  let ParserMatchClass = FPImmOperand;
1333  let PrintMethod = "printFPImmOperand";
1334}
1335
1336def fpimm8 : Operand<i32> {
1337  let ParserMatchClass = FPImmOperand;
1338  let PrintMethod = "printFPImmOperand";
1339}
1340
1341def fpimm0 : FPImmLeaf<fAny, [{
1342  return Imm.isExactlyValue(+0.0);
1343}]>;
1344
1345def fpimm_minus0 : FPImmLeaf<fAny, [{
1346  return Imm.isExactlyValue(-0.0);
1347}]>;
1348
1349def fpimm_half : FPImmLeaf<fAny, [{
1350  return Imm.isExactlyValue(+0.5);
1351}]>;
1352
1353def fpimm_one : FPImmLeaf<fAny, [{
1354  return Imm.isExactlyValue(+1.0);
1355}]>;
1356
1357def fpimm_two : FPImmLeaf<fAny, [{
1358  return Imm.isExactlyValue(+2.0);
1359}]>;
1360
1361def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1362  GISDNodeXFormEquiv<fpimm16XForm>;
1363def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1364  GISDNodeXFormEquiv<fpimm32XForm>;
1365def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1366  GISDNodeXFormEquiv<fpimm64XForm>;
1367def gi_fpimm32SIMDModImmType4 :
1368    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1369  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1370
1371// Vector lane operands
1372class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1373  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1374  let DiagnosticType = "Invalid" # Name;
1375  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1376  let RenderMethod = "addVectorIndexOperands";
1377}
1378
1379class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1380    : Operand<ty> {
1381  let ParserMatchClass = mc;
1382  let PrintMethod = "printVectorIndex";
1383}
1384
1385multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1386  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1387  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1388}
1389
1390def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1391def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1392def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1393def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1394def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1395def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1396
1397let OperandNamespace = "AArch64" in {
1398  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1399    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1400                                [{ return ((uint64_t)Imm) == 0; }]>;
1401  }
1402}
1403defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1404                                [{ return ((uint64_t)Imm) == 1; }]>;
1405defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1406                                [{ return ((uint64_t)Imm) < 16; }]>;
1407defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1408                                [{ return ((uint64_t)Imm) < 8; }]>;
1409defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1410                                [{ return ((uint64_t)Imm) < 4; }]>;
1411defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1412                                [{ return ((uint64_t)Imm) < 2; }]>;
1413
1414defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1415                                   [{ return ((uint64_t)Imm) == 1; }]>;
1416defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1417                                   [{ return ((uint64_t)Imm) < 16; }]>;
1418defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1419                                   [{ return ((uint64_t)Imm) < 8; }]>;
1420defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1421                                   [{ return ((uint64_t)Imm) < 4; }]>;
1422defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1423                                   [{ return ((uint64_t)Imm) < 2; }]>;
1424
1425def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1426def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1427def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1428def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1429def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1430
1431defm sve_elm_idx_extdup_b
1432  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1433                [{ return ((uint64_t)Imm) < 64; }]>;
1434defm sve_elm_idx_extdup_h
1435  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1436                [{ return ((uint64_t)Imm) < 32; }]>;
1437defm sve_elm_idx_extdup_s
1438  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1439                [{ return ((uint64_t)Imm) < 16; }]>;
1440defm sve_elm_idx_extdup_d
1441  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1442                [{ return ((uint64_t)Imm) < 8; }]>;
1443defm sve_elm_idx_extdup_q
1444  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1445                [{ return ((uint64_t)Imm) < 4; }]>;
1446
1447def sme_elm_idx0_0 : Operand<i32>, TImmLeaf<i32, [{
1448  return ((uint32_t)Imm) == 0;
1449}]> {
1450  let ParserMatchClass = Imm0_0Operand;
1451  let PrintMethod = "printMatrixIndex";
1452  let OperandNamespace = "AArch64";
1453  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1454}
1455def sme_elm_idx0_1 : Operand<i32>, TImmLeaf<i32, [{
1456  return ((uint32_t)Imm) <= 1;
1457}]> {
1458  let ParserMatchClass = Imm0_1Operand;
1459  let PrintMethod = "printMatrixIndex";
1460}
1461def sme_elm_idx0_3 : Operand<i32>, TImmLeaf<i32, [{
1462  return ((uint32_t)Imm) <= 3;
1463}]> {
1464  let ParserMatchClass = Imm0_3Operand;
1465  let PrintMethod = "printMatrixIndex";
1466}
1467def sme_elm_idx0_7 : Operand<i32>, TImmLeaf<i32, [{
1468  return ((uint32_t)Imm) <= 7;
1469}]> {
1470  let ParserMatchClass = Imm0_7Operand;
1471  let PrintMethod = "printMatrixIndex";
1472}
1473def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
1474  return ((uint32_t)Imm) <= 15;
1475}]> {
1476  let ParserMatchClass = Imm0_15Operand;
1477  let PrintMethod = "printMatrixIndex";
1478}
1479
1480// SME2 vector select offset operands
1481
1482// uimm3s8 predicate
1483// True if the immediate is a multiple of 8 in the range [0,56].
1484def UImm3s8Operand : UImmScaledMemoryIndexed<3, 8>;
1485
1486def uimm3s8 : Operand<i64>, ImmLeaf<i64,
1487[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
1488  let PrintMethod = "printVectorIndex<8>";
1489  let ParserMatchClass = UImm3s8Operand;
1490}
1491
1492class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
1493  let Name = "UImm" # Width # "s" # Scale # "Range";
1494  let DiagnosticType = "InvalidMemoryIndexedRange" # Scale # "UImm" # Width;
1495  let RenderMethod = "addImmScaledRangeOperands<" # Scale # ">";
1496  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ", " # OffsetVal # ", /*IsRange=*/true>";
1497  let ParserMethod = "tryParseImmRange";
1498}
1499
1500// Implicit immediate ranges 0:1 and 0:3, scale has no meaning
1501// since the immediate is zero
1502def UImm0s2RangeOperand : UImmScaledMemoryIndexedRange<0, 2, 1>;
1503def UImm0s4RangeOperand : UImmScaledMemoryIndexedRange<0, 4, 3>;
1504
1505def UImm1s2RangeOperand : UImmScaledMemoryIndexedRange<1, 2, 1>;
1506def UImm1s4RangeOperand : UImmScaledMemoryIndexedRange<1, 4, 3>;
1507def UImm2s2RangeOperand : UImmScaledMemoryIndexedRange<2, 2, 1>;
1508def UImm2s4RangeOperand : UImmScaledMemoryIndexedRange<2, 4, 3>;
1509def UImm3s2RangeOperand : UImmScaledMemoryIndexedRange<3, 2, 1>;
1510
1511def uimm0s2range : Operand<i64>, ImmLeaf<i64,
1512[{ return Imm == 0; }], UImmS1XForm> {
1513  let PrintMethod = "printImmRangeScale<2, 1>";
1514  let ParserMatchClass = UImm0s2RangeOperand;
1515  let OperandNamespace = "AArch64";
1516  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1517}
1518
1519def uimm0s4range : Operand<i64>, ImmLeaf<i64,
1520[{ return Imm == 0; }], UImmS1XForm> {
1521  let PrintMethod = "printImmRangeScale<4, 3>";
1522  let ParserMatchClass = UImm0s4RangeOperand;
1523  let OperandNamespace = "AArch64";
1524  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1525}
1526
1527def uimm1s2range : Operand<i64>, ImmLeaf<i64,
1528[{ return Imm >= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> {
1529  let PrintMethod = "printImmRangeScale<2, 1>";
1530  let ParserMatchClass = UImm1s2RangeOperand;
1531}
1532
1533def uimm1s4range : Operand<i64>, ImmLeaf<i64,
1534[{ return Imm >= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> {
1535  let PrintMethod = "printImmRangeScale<4, 3>";
1536  let ParserMatchClass = UImm1s4RangeOperand;
1537}
1538
1539def uimm2s2range : Operand<i64>, ImmLeaf<i64,
1540[{ return Imm >= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> {
1541  let PrintMethod = "printImmRangeScale<2, 1>";
1542  let ParserMatchClass = UImm2s2RangeOperand;
1543}
1544
1545def uimm2s4range : Operand<i64>, ImmLeaf<i64,
1546[{ return Imm >= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> {
1547  let PrintMethod = "printImmRangeScale<4, 3>";
1548  let ParserMatchClass = UImm2s4RangeOperand;
1549}
1550
1551def uimm3s2range : Operand<i64>, ImmLeaf<i64,
1552[{ return Imm >= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> {
1553  let PrintMethod = "printImmRangeScale<2, 1>";
1554  let ParserMatchClass = UImm3s2RangeOperand;
1555}
1556
1557
1558// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1559// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1560// are encoded as the eight bit value 'abcdefgh'.
1561def simdimmtype10 : Operand<i32>,
1562                    FPImmLeaf<f64, [{
1563      return AArch64_AM::isAdvSIMDModImmType10(
1564                 Imm.bitcastToAPInt().getZExtValue());
1565    }], SDNodeXForm<fpimm, [{
1566      APFloat InVal = N->getValueAPF();
1567      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1568                                                           .bitcastToAPInt()
1569                                                           .getZExtValue());
1570      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1571    }]>> {
1572  let ParserMatchClass = SIMDImmType10Operand;
1573  let PrintMethod = "printSIMDType10Operand";
1574}
1575
1576
1577//---
1578// System management
1579//---
1580
1581// Base encoding for system instruction operands.
1582let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1583class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1584                  list<dag> pattern = []>
1585    : I<oops, iops, asm, operands, "", pattern> {
1586  let Inst{31-22} = 0b1101010100;
1587  let Inst{21}    = L;
1588}
1589
1590// System instructions which do not have an Rt register.
1591class SimpleSystemI<bit L, dag iops, string asm, string operands,
1592                    list<dag> pattern = []>
1593    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1594  let Inst{4-0} = 0b11111;
1595}
1596
1597// System instructions which have an Rt register.
1598class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1599                list<dag> pattern = []>
1600    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1601      Sched<[WriteSys]> {
1602  bits<5> Rt;
1603  let Inst{4-0} = Rt;
1604}
1605
1606// System instructions for transactional memory extension
1607class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1608                    string asm, string operands, list<dag> pattern>
1609    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1610      Sched<[WriteSys]> {
1611  let Inst{20-12} = 0b000110011;
1612  let Inst{11-8} = CRm;
1613  let Inst{7-5} = op2;
1614  let DecoderMethod = "";
1615
1616  let mayLoad = 1;
1617  let mayStore = 1;
1618}
1619
1620// System instructions for transactional memory - single input operand
1621class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1622    : TMBaseSystemI<0b1, CRm, 0b011,
1623                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1624  bits<5> Rt;
1625  let Inst{4-0} = Rt;
1626}
1627
1628// System instructions that pass a register argument
1629// This class assumes the register is for input rather than output.
1630class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1631                      list<dag> pattern = []>
1632    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1633  let Inst{20-12} = 0b000110001;
1634  let Inst{11-8} = CRm;
1635  let Inst{7-5} = Op2;
1636}
1637
1638// System instructions for transactional memory - no operand
1639class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1640    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1641  let Inst{4-0} = 0b11111;
1642}
1643
1644// System instructions for exit from transactions
1645class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1646    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1647      Sched<[WriteSys]> {
1648  bits<16> imm;
1649  let Inst{31-24} = 0b11010100;
1650  let Inst{23-21} = op1;
1651  let Inst{20-5}  = imm;
1652  let Inst{4-0}   = 0b00000;
1653}
1654
1655// Hint instructions that take both a CRm and a 3-bit immediate.
1656// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1657// model patterns with sufficiently fine granularity
1658let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1659  class HintI<string mnemonic>
1660      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1661                      [(int_aarch64_hint imm0_127:$imm)]>,
1662        Sched<[WriteHint]> {
1663    bits <7> imm;
1664    let Inst{20-12} = 0b000110010;
1665    let Inst{11-5} = imm;
1666  }
1667
1668// System instructions taking a single literal operand which encodes into
1669// CRm. op2 differentiates the opcodes.
1670def BarrierAsmOperand : AsmOperandClass {
1671  let Name = "Barrier";
1672  let ParserMethod = "tryParseBarrierOperand";
1673}
1674def barrier_op : Operand<i32> {
1675  let PrintMethod = "printBarrierOption";
1676  let ParserMatchClass = BarrierAsmOperand;
1677}
1678def BarriernXSAsmOperand : AsmOperandClass {
1679  let Name = "BarriernXS";
1680  let ParserMethod = "tryParseBarriernXSOperand";
1681}
1682def barrier_nxs_op : Operand<i32> {
1683  let PrintMethod = "printBarriernXSOption";
1684  let ParserMatchClass = BarriernXSAsmOperand;
1685}
1686class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1687                 list<dag> pattern = []>
1688    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1689      Sched<[WriteBarrier]> {
1690  bits<4> CRm;
1691  let Inst{20-12} = 0b000110011;
1692  let Inst{11-8} = CRm;
1693  let Inst{7-5} = opc;
1694}
1695
1696class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1697    : SimpleSystemI<0, (ins), asm, "", pattern>,
1698      Sched<[WriteHint]> {
1699  bits<4> CRm;
1700  let CRm = 0b0011;
1701  let Inst{31-12} = 0b11010101000000110010;
1702  let Inst{11-8} = CRm;
1703  let Inst{7-5} = op2;
1704  let Inst{4-0} = 0b11111;
1705}
1706
1707// MRS/MSR system instructions. These have different operand classes because
1708// a different subset of registers can be accessed through each instruction.
1709def MRSSystemRegisterOperand : AsmOperandClass {
1710  let Name = "MRSSystemRegister";
1711  let ParserMethod = "tryParseSysReg";
1712  let DiagnosticType = "MRS";
1713}
1714// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1715def mrs_sysreg_op : Operand<i32> {
1716  let ParserMatchClass = MRSSystemRegisterOperand;
1717  let DecoderMethod = "DecodeMRSSystemRegister";
1718  let PrintMethod = "printMRSSystemRegister";
1719}
1720
1721def MSRSystemRegisterOperand : AsmOperandClass {
1722  let Name = "MSRSystemRegister";
1723  let ParserMethod = "tryParseSysReg";
1724  let DiagnosticType = "MSR";
1725}
1726def msr_sysreg_op : Operand<i32> {
1727  let ParserMatchClass = MSRSystemRegisterOperand;
1728  let DecoderMethod = "DecodeMSRSystemRegister";
1729  let PrintMethod = "printMSRSystemRegister";
1730}
1731
1732def PSBHintOperand : AsmOperandClass {
1733  let Name = "PSBHint";
1734  let ParserMethod = "tryParsePSBHint";
1735}
1736def psbhint_op : Operand<i32> {
1737  let ParserMatchClass = PSBHintOperand;
1738  let PrintMethod = "printPSBHintOp";
1739  let MCOperandPredicate = [{
1740    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1741    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1742    if (!MCOp.isImm())
1743      return false;
1744    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1745  }];
1746}
1747
1748def BTIHintOperand : AsmOperandClass {
1749  let Name = "BTIHint";
1750  let ParserMethod = "tryParseBTIHint";
1751}
1752def btihint_op : Operand<i32> {
1753  let ParserMatchClass = BTIHintOperand;
1754  let PrintMethod = "printBTIHintOp";
1755  let MCOperandPredicate = [{
1756    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1757    if (!MCOp.isImm())
1758      return false;
1759    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1760  }];
1761}
1762
1763class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1764                       "mrs", "\t$Rt, $systemreg"> {
1765  bits<16> systemreg;
1766  let Inst{20-5} = systemreg;
1767  let DecoderNamespace = "Fallback";
1768  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1769  // require doing this. The alternative was to explicitly model each one, but
1770  // it feels like it is unnecessary because it seems there are no negative
1771  // consequences setting these flags for all.
1772  let Defs = [NZCV];
1773}
1774
1775// FIXME: Some of these def NZCV, others don't. Best way to model that?
1776// Explicitly modeling each of the system register as a register class
1777// would do it, but feels like overkill at this point.
1778class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1779                       "msr", "\t$systemreg, $Rt"> {
1780  bits<16> systemreg;
1781  let Inst{20-5} = systemreg;
1782  let DecoderNamespace = "Fallback";
1783}
1784
1785def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1786  let Name = "SystemPStateFieldWithImm0_15";
1787  let ParserMethod = "tryParseSysReg";
1788}
1789def pstatefield4_op : Operand<i32> {
1790  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1791  let PrintMethod = "printSystemPStateField";
1792  let MCOperandPredicate = [{
1793    if (!MCOp.isImm())
1794      return false;
1795    return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr;
1796  }];
1797}
1798
1799// Instructions to modify PSTATE, no input reg
1800let Defs = [NZCV] in
1801class PstateWriteSimple<dag iops, string asm, string operands>
1802  : SimpleSystemI<0, iops, asm, operands> {
1803
1804  let Inst{20-19} = 0b00;
1805  let Inst{15-12} = 0b0100;
1806}
1807
1808class MSRpstateImm0_15
1809  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1810                  "\t$pstatefield, $imm">,
1811    Sched<[WriteSys]> {
1812
1813  bits<6> pstatefield;
1814  bits<4> imm;
1815  let Inst{18-16} = pstatefield{5-3};
1816  let Inst{11-8} = imm;
1817  let Inst{7-5} = pstatefield{2-0};
1818
1819  let DecoderMethod = "DecodeSystemPStateImm0_15Instruction";
1820  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1821  // Fail the decoder should attempt to decode the instruction as MSRI.
1822  let hasCompleteDecoder = false;
1823}
1824
1825def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1826  let Name = "SystemPStateFieldWithImm0_1";
1827  let ParserMethod = "tryParseSysReg";
1828}
1829def pstatefield1_op : Operand<i32> {
1830  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1831  let PrintMethod = "printSystemPStateField";
1832  let MCOperandPredicate = [{
1833    if (!MCOp.isImm())
1834      return false;
1835    return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr;
1836  }];
1837}
1838
1839class MSRpstateImm0_1
1840  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1841                 "\t$pstatefield, $imm">,
1842    Sched<[WriteSys]> {
1843
1844  bits<9> pstatefield;
1845  bit imm;
1846  let Inst{18-16} = pstatefield{5-3};
1847  let Inst{11-9} = pstatefield{8-6};
1848  let Inst{8} = imm;
1849  let Inst{7-5} = pstatefield{2-0};
1850
1851  let DecoderMethod = "DecodeSystemPStateImm0_1Instruction";
1852  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1853  // Fail the decoder should attempt to decode the instruction as MSRI.
1854  let hasCompleteDecoder = false;
1855  let DecoderNamespace = "Fallback";
1856}
1857
1858// SYS and SYSL generic system instructions.
1859def SysCRAsmOperand : AsmOperandClass {
1860  let Name = "SysCR";
1861  let ParserMethod = "tryParseSysCROperand";
1862}
1863
1864def sys_cr_op : Operand<i32> {
1865  let PrintMethod = "printSysCROperand";
1866  let ParserMatchClass = SysCRAsmOperand;
1867}
1868
1869class SystemXtI<bit L, string asm>
1870  : RtSystemI<L, (outs),
1871       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1872       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1873  bits<3> op1;
1874  bits<4> Cn;
1875  bits<4> Cm;
1876  bits<3> op2;
1877  let Inst{20-19} = 0b01;
1878  let Inst{18-16} = op1;
1879  let Inst{15-12} = Cn;
1880  let Inst{11-8}  = Cm;
1881  let Inst{7-5}   = op2;
1882}
1883
1884class SystemLXtI<bit L, string asm>
1885  : RtSystemI<L, (outs),
1886       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1887       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1888  bits<3> op1;
1889  bits<4> Cn;
1890  bits<4> Cm;
1891  bits<3> op2;
1892  let Inst{20-19} = 0b01;
1893  let Inst{18-16} = op1;
1894  let Inst{15-12} = Cn;
1895  let Inst{11-8}  = Cm;
1896  let Inst{7-5}   = op2;
1897}
1898
1899def RangePrefetchOperand : AsmOperandClass {
1900  let Name = "RangePrefetch";
1901  let ParserMethod = "tryParseRPRFMOperand";
1902  let PredicateMethod = "isPrefetch";
1903  let RenderMethod = "addPrefetchOperands";
1904}
1905
1906def rprfop : Operand<i32>, TImmLeaf<i32, [{
1907    return (((uint32_t)Imm) <= 63);
1908  }]> {
1909  let PrintMethod = "printRPRFMOperand";
1910  let ParserMatchClass = RangePrefetchOperand;
1911}
1912
1913// Branch (register) instructions:
1914//
1915//  case opc of
1916//    0001 blr
1917//    0000 br
1918//    0101 dret
1919//    0100 eret
1920//    0010 ret
1921//    otherwise UNDEFINED
1922class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1923                    string operands, list<dag> pattern>
1924    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1925  let Inst{31-25} = 0b1101011;
1926  let Inst{24-21} = opc;
1927  let Inst{20-16} = 0b11111;
1928  let Inst{15-10} = 0b000000;
1929  let Inst{4-0}   = 0b00000;
1930}
1931
1932class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1933    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1934  bits<5> Rn;
1935  let Inst{9-5} = Rn;
1936}
1937
1938let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1939class SpecialReturn<bits<4> opc, string asm>
1940    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1941  let Inst{9-5} = 0b11111;
1942}
1943
1944let mayLoad = 1 in
1945class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1946  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1947  Sched<[]> {
1948  bits<5> Rn;
1949  bits<5> Rt;
1950  let Inst{31-30} = sz;
1951  let Inst{29-10} = 0b11100010111111110000;
1952  let Inst{9-5} = Rn;
1953  let Inst{4-0} = Rt;
1954}
1955
1956class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1957               list<dag> pattern>
1958  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1959  let isAuthenticated = 1;
1960  let Inst{31-25} = 0b1101011;
1961  let Inst{20-11} = 0b1111100001;
1962  let Inst{10} = M;
1963  let Inst{4-0} = 0b11111;
1964}
1965
1966class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1967  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1968  bits<5> Rn;
1969  bits<5> Rm;
1970  let Inst{24-22} = 0b100;
1971  let Inst{21} = op;
1972  let Inst{9-5} = Rn;
1973  let Inst{4-0} = Rm;
1974}
1975
1976class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1977  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1978  bits<5> Rn;
1979  let Inst{24} = 0;
1980  let Inst{23-21} = opc;
1981  let Inst{9-5} = Rn;
1982}
1983
1984let Uses = [LR,SP] in
1985class AuthReturn<bits<3> op, bits<1> M, string asm>
1986  : AuthBase<M, (outs), (ins), asm, "", []> {
1987  let Inst{24} = 0;
1988  let Inst{23-21} = op;
1989  let Inst{9-0} = 0b1111111111;
1990}
1991
1992let mayLoad = 1 in
1993class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1994                   string operands, string cstr>
1995  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1996  bits<10> offset;
1997  bits<5> Rn;
1998  bits<5> Rt;
1999  let isAuthenticated = 1;
2000  let Inst{31-24} = 0b11111000;
2001  let Inst{23} = M;
2002  let Inst{22} = offset{9};
2003  let Inst{21} = 1;
2004  let Inst{20-12} = offset{8-0};
2005  let Inst{11} = W;
2006  let Inst{10} = 1;
2007  let Inst{9-5} = Rn;
2008  let Inst{4-0} = Rt;
2009
2010  let DecoderMethod = "DecodeAuthLoadInstruction";
2011}
2012
2013multiclass AuthLoad<bit M, string asm, Operand opr> {
2014  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
2015                               (ins GPR64sp:$Rn, opr:$offset),
2016                               asm, "\t$Rt, [$Rn, $offset]", "">;
2017  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
2018                               (ins GPR64sp:$Rn, opr:$offset),
2019                               asm, "\t$Rt, [$Rn, $offset]!",
2020                               "$Rn = $wback,@earlyclobber $wback">;
2021
2022  def : InstAlias<asm # "\t$Rt, [$Rn]",
2023                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
2024
2025  def : InstAlias<asm # "\t$Rt, [$wback]!",
2026                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
2027}
2028
2029//---
2030// Conditional branch instruction.
2031//---
2032
2033// Condition code.
2034// 4-bit immediate. Pretty-printed as <cc>
2035def ccode : Operand<i32> {
2036  let PrintMethod = "printCondCode";
2037  let ParserMatchClass = CondCode;
2038}
2039def inv_ccode : Operand<i32> {
2040  // AL and NV are invalid in the aliases which use inv_ccode
2041  let PrintMethod = "printInverseCondCode";
2042  let ParserMatchClass = CondCode;
2043  let MCOperandPredicate = [{
2044    return MCOp.isImm() &&
2045           MCOp.getImm() != AArch64CC::AL &&
2046           MCOp.getImm() != AArch64CC::NV;
2047  }];
2048}
2049
2050// Conditional branch target. 19-bit immediate. The low two bits of the target
2051// offset are implied zero and so are not part of the immediate.
2052def am_brcond : Operand<OtherVT> {
2053  let EncoderMethod = "getCondBranchTargetOpValue";
2054  let DecoderMethod = "DecodePCRelLabel19";
2055  let PrintMethod = "printAlignedLabel";
2056  let ParserMatchClass = PCRelLabel19Operand;
2057  let OperandType = "OPERAND_PCREL";
2058}
2059
2060class BranchCond<bit bit4, string mnemonic>
2061   : I<(outs), (ins ccode:$cond, am_brcond:$target),
2062       mnemonic, ".$cond\t$target", "",
2063       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
2064  let isBranch = 1;
2065  let isTerminator = 1;
2066  let Uses = [NZCV];
2067
2068  bits<4> cond;
2069  bits<19> target;
2070  let Inst{31-24} = 0b01010100;
2071  let Inst{23-5} = target;
2072  let Inst{4} = bit4;
2073  let Inst{3-0} = cond;
2074}
2075
2076//---
2077// Compare-and-branch instructions.
2078//---
2079class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
2080    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
2081         asm, "\t$Rt, $target", "",
2082         [(node regtype:$Rt, bb:$target)]>,
2083      Sched<[WriteBr]> {
2084  let isBranch = 1;
2085  let isTerminator = 1;
2086
2087  bits<5> Rt;
2088  bits<19> target;
2089  let Inst{30-25} = 0b011010;
2090  let Inst{24}    = op;
2091  let Inst{23-5}  = target;
2092  let Inst{4-0}   = Rt;
2093}
2094
2095multiclass CmpBranch<bit op, string asm, SDNode node> {
2096  def W : BaseCmpBranch<GPR32, op, asm, node> {
2097    let Inst{31} = 0;
2098  }
2099  def X : BaseCmpBranch<GPR64, op, asm, node> {
2100    let Inst{31} = 1;
2101  }
2102}
2103
2104//---
2105// Test-bit-and-branch instructions.
2106//---
2107// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
2108// the target offset are implied zero and so are not part of the immediate.
2109def am_tbrcond : Operand<OtherVT> {
2110  let EncoderMethod = "getTestBranchTargetOpValue";
2111  let PrintMethod = "printAlignedLabel";
2112  let ParserMatchClass = BranchTarget14Operand;
2113  let OperandType = "OPERAND_PCREL";
2114}
2115
2116// AsmOperand classes to emit (or not) special diagnostics
2117def TBZImm0_31Operand : AsmOperandClass {
2118  let Name = "TBZImm0_31";
2119  let PredicateMethod = "isImmInRange<0,31>";
2120  let RenderMethod = "addImmOperands";
2121}
2122def TBZImm32_63Operand : AsmOperandClass {
2123  let Name = "Imm32_63";
2124  let PredicateMethod = "isImmInRange<32,63>";
2125  let DiagnosticType = "InvalidImm0_63";
2126  let RenderMethod = "addImmOperands";
2127}
2128
2129class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
2130  return (((uint32_t)Imm) < 32);
2131}]> {
2132  let ParserMatchClass = matcher;
2133}
2134
2135def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
2136def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
2137
2138def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
2139  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
2140}]> {
2141  let ParserMatchClass = TBZImm32_63Operand;
2142}
2143
2144class BaseTestBranch<RegisterClass regtype, Operand immtype,
2145                     bit op, string asm, SDNode node>
2146    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
2147       asm, "\t$Rt, $bit_off, $target", "",
2148       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
2149      Sched<[WriteBr]> {
2150  let isBranch = 1;
2151  let isTerminator = 1;
2152
2153  bits<5> Rt;
2154  bits<6> bit_off;
2155  bits<14> target;
2156
2157  let Inst{30-25} = 0b011011;
2158  let Inst{24}    = op;
2159  let Inst{23-19} = bit_off{4-0};
2160  let Inst{18-5}  = target;
2161  let Inst{4-0}   = Rt;
2162
2163  let DecoderMethod = "DecodeTestAndBranch";
2164}
2165
2166multiclass TestBranch<bit op, string asm, SDNode node> {
2167  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
2168    let Inst{31} = 0;
2169  }
2170
2171  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
2172    let Inst{31} = 1;
2173  }
2174
2175  // Alias X-reg with 0-31 imm to W-Reg.
2176  def : InstAlias<asm # "\t$Rd, $imm, $target",
2177                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
2178                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
2179  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
2180            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
2181            tbz_imm0_31_diag:$imm, bb:$target)>;
2182}
2183
2184//---
2185// Unconditional branch (immediate) instructions.
2186//---
2187def am_b_target : Operand<OtherVT> {
2188  let EncoderMethod = "getBranchTargetOpValue";
2189  let PrintMethod = "printAlignedLabel";
2190  let ParserMatchClass = BranchTarget26Operand;
2191  let OperandType = "OPERAND_PCREL";
2192}
2193def am_bl_target : Operand<i64> {
2194  let EncoderMethod = "getBranchTargetOpValue";
2195  let PrintMethod = "printAlignedLabel";
2196  let ParserMatchClass = BranchTarget26Operand;
2197  let OperandType = "OPERAND_PCREL";
2198}
2199
2200class BImm<bit op, dag iops, string asm, list<dag> pattern>
2201    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
2202  bits<26> addr;
2203  let Inst{31}    = op;
2204  let Inst{30-26} = 0b00101;
2205  let Inst{25-0}  = addr;
2206
2207  let DecoderMethod = "DecodeUnconditionalBranch";
2208}
2209
2210class BranchImm<bit op, string asm, list<dag> pattern>
2211    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2212class CallImm<bit op, string asm, list<dag> pattern>
2213    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2214
2215//---
2216// Basic one-operand data processing instructions.
2217//---
2218
2219let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2220class BaseOneOperandData<bit sf, bit S, bits<5> opc2, bits<6> opc,
2221                         RegisterClass regtype, string asm,
2222                         SDPatternOperator node>
2223  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2224      [(set regtype:$Rd, (node regtype:$Rn))]>,
2225    Sched<[WriteI, ReadI]> {
2226  bits<5> Rd;
2227  bits<5> Rn;
2228
2229  let Inst{31} = sf;
2230  let Inst{30} = 0b1;
2231  let Inst{29} = S;
2232  let Inst{28-21} = 0b11010110;
2233  let Inst{20-16} = opc2;
2234  let Inst{15-10} = opc;
2235  let Inst{9-5}   = Rn;
2236  let Inst{4-0}   = Rd;
2237}
2238
2239let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2240multiclass OneOperandData<bits<6> opc, string asm,
2241                          SDPatternOperator node = null_frag> {
2242  def Wr : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2243
2244  def Xr : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2245}
2246
2247class OneWRegData<bits<6> opc, string asm, SDPatternOperator node>
2248    : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2249
2250class OneXRegData<bits<6> opc, string asm, SDPatternOperator node>
2251    : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2252
2253class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2254                      SDPatternOperator op>
2255  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2256      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2257    Sched<[WriteI, ReadI]> {
2258  bits<5> Rd;
2259  bits<5> Rn;
2260  let Inst{31-15} = 0b11011010110000010;
2261  let Inst{14-12} = opcode_prefix;
2262  let Inst{11-10} = opcode;
2263  let Inst{9-5} = Rn;
2264  let Inst{4-0} = Rd;
2265}
2266
2267class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2268                   SDPatternOperator op>
2269  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2270      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2271    Sched<[]> {
2272  bits<5> Rd;
2273  let Inst{31-15} = 0b11011010110000010;
2274  let Inst{14-12} = opcode_prefix;
2275  let Inst{11-10} = opcode;
2276  let Inst{9-5} = 0b11111;
2277  let Inst{4-0} = Rd;
2278}
2279
2280class SignAuthTwoOperand<bits<4> opc, string asm,
2281                         SDPatternOperator OpNode>
2282  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2283      asm, "\t$Rd, $Rn, $Rm", "",
2284      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2285    Sched<[WriteI, ReadI, ReadI]> {
2286  bits<5> Rd;
2287  bits<5> Rn;
2288  bits<5> Rm;
2289  let Inst{31-21} = 0b10011010110;
2290  let Inst{20-16} = Rm;
2291  let Inst{15-14} = 0b00;
2292  let Inst{13-10} = opc;
2293  let Inst{9-5}   = Rn;
2294  let Inst{4-0}   = Rd;
2295}
2296
2297class ClearAuth<bits<1> data, string asm>
2298  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2299  bits<5> Rd;
2300  let Inst{31-11} = 0b110110101100000101000;
2301  let Inst{10} = data;
2302  let Inst{9-5} = 0b11111;
2303  let Inst{4-0} = Rd;
2304}
2305
2306// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2307class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2308    : I<(outs), iops, asm, ops, "", []>,
2309      Sched<[WriteI, ReadI, ReadI]> {
2310  let Uses = [NZCV];
2311  let Defs = [NZCV];
2312  bits<5> Rn;
2313  let Inst{31}    = sf;
2314  let Inst{30-15} = 0b0111010000000000;
2315  let Inst{14}    = sz;
2316  let Inst{13-10} = 0b0010;
2317  let Inst{9-5}   = Rn;
2318  let Inst{4-0}   = 0b01101;
2319}
2320
2321class FlagRotate<dag iops, string asm, string ops>
2322    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2323  bits<6> imm;
2324  bits<4> mask;
2325  let Inst{20-15} = imm;
2326  let Inst{13-10} = 0b0001;
2327  let Inst{4}     = 0b0;
2328  let Inst{3-0}   = mask;
2329}
2330
2331//---
2332// Basic two-operand data processing instructions.
2333//---
2334class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2335                          list<dag> pattern>
2336    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2337        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2338      Sched<[WriteI, ReadI, ReadI]> {
2339  let Uses = [NZCV];
2340  bits<5> Rd;
2341  bits<5> Rn;
2342  bits<5> Rm;
2343  let Inst{30}    = isSub;
2344  let Inst{28-21} = 0b11010000;
2345  let Inst{20-16} = Rm;
2346  let Inst{15-10} = 0;
2347  let Inst{9-5}   = Rn;
2348  let Inst{4-0}   = Rd;
2349}
2350
2351class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2352                      SDNode OpNode>
2353    : BaseBaseAddSubCarry<isSub, regtype, asm,
2354        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2355
2356class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2357                              SDNode OpNode>
2358    : BaseBaseAddSubCarry<isSub, regtype, asm,
2359        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2360         (implicit NZCV)]> {
2361  let Defs = [NZCV];
2362}
2363
2364multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2365                       SDNode OpNode, SDNode OpNode_setflags> {
2366  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2367    let Inst{31} = 0;
2368    let Inst{29} = 0;
2369  }
2370  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2371    let Inst{31} = 1;
2372    let Inst{29} = 0;
2373  }
2374
2375  // Sets flags.
2376  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2377                                    OpNode_setflags> {
2378    let Inst{31} = 0;
2379    let Inst{29} = 1;
2380  }
2381  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2382                                    OpNode_setflags> {
2383    let Inst{31} = 1;
2384    let Inst{29} = 1;
2385  }
2386}
2387
2388class BaseTwoOperandRegReg<bit sf, bit S, bits<6> opc, RegisterClass regtype,
2389                           string asm, SDPatternOperator OpNode,
2390                           RegisterClass in1regtype = regtype,
2391                           RegisterClass in2regtype = regtype>
2392  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2393      asm, "\t$Rd, $Rn, $Rm", "",
2394      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2395  bits<5> Rd;
2396  bits<5> Rn;
2397  bits<5> Rm;
2398  let Inst{31}    = sf;
2399  let Inst{30}    = 0b0;
2400  let Inst{29}    = S;
2401  let Inst{28-21} = 0b11010110;
2402  let Inst{20-16} = Rm;
2403  let Inst{15-10} = opc;
2404  let Inst{9-5}   = Rn;
2405  let Inst{4-0}   = Rd;
2406}
2407
2408class BaseDiv<bit size, bit isSigned, RegisterClass regtype, string asm,
2409              SDPatternOperator OpNode>
2410    : BaseTwoOperandRegReg<size, 0b0, {0,0,0,0,1,?}, regtype, asm, OpNode> {
2411  let Inst{10}    = isSigned;
2412}
2413
2414multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2415  def Wr : BaseDiv<0b0, isSigned, GPR32, asm, OpNode>,
2416           Sched<[WriteID32, ReadID, ReadID]>;
2417
2418  def Xr : BaseDiv<0b1, isSigned, GPR64, asm, OpNode>,
2419           Sched<[WriteID64, ReadID, ReadID]>;
2420}
2421
2422class BaseShift<bit size, bits<2> shift_type, RegisterClass regtype, string asm,
2423                SDPatternOperator OpNode = null_frag>
2424  : BaseTwoOperandRegReg<size, 0b0, {0,0,1,0,?,?}, regtype, asm, OpNode>,
2425    Sched<[WriteIS, ReadI]> {
2426  let Inst{11-10} = shift_type;
2427}
2428
2429multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2430  def Wr : BaseShift<0b0, shift_type, GPR32, asm>;
2431
2432  def Xr : BaseShift<0b1, shift_type, GPR64, asm, OpNode>;
2433
2434  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2435            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2436                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2437
2438  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2439            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2440
2441  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2442            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2443
2444  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2445            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2446
2447  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2448            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2449                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2450
2451  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2452            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2453                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2454}
2455
2456class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2457    : InstAlias<asm#"\t$dst, $src1, $src2",
2458                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2459
2460class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2461                       RegisterClass addtype, string asm,
2462                       list<dag> pattern>
2463  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2464      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2465  bits<5> Rd;
2466  bits<5> Rn;
2467  bits<5> Rm;
2468  bits<5> Ra;
2469  let Inst{30-24} = 0b0011011;
2470  let Inst{23-21} = opc;
2471  let Inst{20-16} = Rm;
2472  let Inst{15}    = isSub;
2473  let Inst{14-10} = Ra;
2474  let Inst{9-5}   = Rn;
2475  let Inst{4-0}   = Rd;
2476}
2477
2478multiclass MulAccum<bit isSub, string asm> {
2479  // MADD/MSUB generation is decided by MachineCombiner.cpp
2480  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2481      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2482    let Inst{31} = 0;
2483  }
2484
2485  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2486      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2487    let Inst{31} = 1;
2488  }
2489}
2490
2491class WideMulAccum<bit isSub, bits<3> opc, string asm,
2492                   SDNode AccNode, SDNode ExtNode>
2493  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2494    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2495                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2496    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2497  let Inst{31} = 1;
2498}
2499
2500class MulHi<bits<3> opc, string asm, SDNode OpNode>
2501  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2502      asm, "\t$Rd, $Rn, $Rm", "",
2503      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2504    Sched<[WriteIM64, ReadIM, ReadIM]> {
2505  bits<5> Rd;
2506  bits<5> Rn;
2507  bits<5> Rm;
2508  let Inst{31-24} = 0b10011011;
2509  let Inst{23-21} = opc;
2510  let Inst{20-16} = Rm;
2511  let Inst{15}    = 0;
2512  let Inst{9-5}   = Rn;
2513  let Inst{4-0}   = Rd;
2514
2515  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2516  // (i.e. all bits 1) but is ignored by the processor.
2517  let PostEncoderMethod = "fixMulHigh";
2518}
2519
2520class MulAccumWAlias<string asm, Instruction inst>
2521    : InstAlias<asm#"\t$dst, $src1, $src2",
2522                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2523class MulAccumXAlias<string asm, Instruction inst>
2524    : InstAlias<asm#"\t$dst, $src1, $src2",
2525                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2526class WideMulAccumAlias<string asm, Instruction inst>
2527    : InstAlias<asm#"\t$dst, $src1, $src2",
2528                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2529
2530class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2531              SDPatternOperator OpNode, string asm>
2532  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2533      asm, "\t$Rd, $Rn, $Rm", "",
2534      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2535    Sched<[WriteISReg, ReadI, ReadISReg]> {
2536  bits<5> Rd;
2537  bits<5> Rn;
2538  bits<5> Rm;
2539
2540  let Inst{31} = sf;
2541  let Inst{30-21} = 0b0011010110;
2542  let Inst{20-16} = Rm;
2543  let Inst{15-13} = 0b010;
2544  let Inst{12} = C;
2545  let Inst{11-10} = sz;
2546  let Inst{9-5} = Rn;
2547  let Inst{4-0} = Rd;
2548  let Predicates = [HasCRC];
2549}
2550
2551//---
2552// Address generation.
2553//---
2554
2555class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2556    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2557        pattern>,
2558      Sched<[WriteI]> {
2559  bits<5>  Xd;
2560  bits<21> label;
2561  let Inst{31}    = page;
2562  let Inst{30-29} = label{1-0};
2563  let Inst{28-24} = 0b10000;
2564  let Inst{23-5}  = label{20-2};
2565  let Inst{4-0}   = Xd;
2566
2567  let DecoderMethod = "DecodeAdrInstruction";
2568}
2569
2570//---
2571// Move immediate.
2572//---
2573
2574def movimm32_imm : Operand<i32> {
2575  let ParserMatchClass = AsmImmRange<0, 65535>;
2576  let EncoderMethod = "getMoveWideImmOpValue";
2577  let PrintMethod = "printImm";
2578}
2579def movimm32_shift : Operand<i32> {
2580  let PrintMethod = "printShifter";
2581  let ParserMatchClass = MovImm32ShifterOperand;
2582}
2583def movimm64_shift : Operand<i32> {
2584  let PrintMethod = "printShifter";
2585  let ParserMatchClass = MovImm64ShifterOperand;
2586}
2587
2588let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2589class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2590                        string asm>
2591  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2592       asm, "\t$Rd, $imm$shift", "", []>,
2593    Sched<[WriteImm]> {
2594  bits<5> Rd;
2595  bits<16> imm;
2596  bits<6> shift;
2597  let Inst{30-29} = opc;
2598  let Inst{28-23} = 0b100101;
2599  let Inst{22-21} = shift{5-4};
2600  let Inst{20-5}  = imm;
2601  let Inst{4-0}   = Rd;
2602
2603  let DecoderMethod = "DecodeMoveImmInstruction";
2604}
2605
2606multiclass MoveImmediate<bits<2> opc, string asm> {
2607  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2608    let Inst{31} = 0;
2609  }
2610
2611  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2612    let Inst{31} = 1;
2613  }
2614}
2615
2616let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2617class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2618                          string asm>
2619  : I<(outs regtype:$Rd),
2620      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2621       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2622    Sched<[WriteI, ReadI]> {
2623  bits<5> Rd;
2624  bits<16> imm;
2625  bits<6> shift;
2626  let Inst{30-29} = opc;
2627  let Inst{28-23} = 0b100101;
2628  let Inst{22-21} = shift{5-4};
2629  let Inst{20-5}  = imm;
2630  let Inst{4-0}   = Rd;
2631
2632  let DecoderMethod = "DecodeMoveImmInstruction";
2633}
2634
2635multiclass InsertImmediate<bits<2> opc, string asm> {
2636  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2637    let Inst{31} = 0;
2638  }
2639
2640  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2641    let Inst{31} = 1;
2642  }
2643}
2644
2645//---
2646// Add/Subtract
2647//---
2648
2649class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2650                    string asm_inst, string asm_ops,
2651                    dag inputs, dag pattern>
2652    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2653      Sched<[WriteI, ReadI]> {
2654  bits<5>  Rd;
2655  bits<5>  Rn;
2656  let Inst{30}    = isSub;
2657  let Inst{29}    = setFlags;
2658  let Inst{28-24} = 0b10001;
2659  let Inst{9-5}   = Rn;
2660  let Inst{4-0}   = Rd;
2661}
2662
2663class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2664                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2665                     string asm_inst, SDPatternOperator OpNode>
2666    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2667                    (ins srcRegtype:$Rn, immtype:$imm),
2668                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2669  bits<14> imm;
2670  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2671  let Inst{21-10} = imm{11-0};
2672  let DecoderMethod = "DecodeAddSubImmShift";
2673}
2674
2675class BaseAddSubRegPseudo<RegisterClass regtype,
2676                          SDPatternOperator OpNode>
2677    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2678             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2679      Sched<[WriteI, ReadI, ReadI]>;
2680
2681class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2682                     arith_shifted_reg shifted_regtype, string asm,
2683                     SDPatternOperator OpNode>
2684    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
2685        asm, "\t$Rd, $Rn, $Rm_and_shift", "",
2686        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm_and_shift))]>,
2687      Sched<[WriteISReg, ReadI, ReadISReg]> {
2688  bits<5> Rd;
2689  bits<5> Rn;
2690  bits<5> Rm;
2691  bits<8> shift;
2692  let Inst{30}    = isSub;
2693  let Inst{29}    = setFlags;
2694  let Inst{28-24} = 0b01011;
2695  let Inst{23-22} = shift{7-6};
2696  let Inst{21}    = 0;
2697  let Inst{20-16} = Rm;
2698  let Inst{15-10} = shift{5-0};
2699  let Inst{9-5}   = Rn;
2700  let Inst{4-0}   = Rd;
2701
2702  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2703}
2704
2705class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2706                     RegisterClass src1Regtype, Operand src2Regtype,
2707                     string asm, SDPatternOperator OpNode>
2708    : I<(outs dstRegtype:$Rd),
2709        (ins src1Regtype:$Rn, (src2Regtype $Rm, $extend):$Rm_and_extend),
2710        asm, "\t$Rd, $Rn, $Rm_and_extend", "",
2711        [(set dstRegtype:$Rd, (OpNode src1Regtype:$Rn, src2Regtype:$Rm_and_extend))]>,
2712      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2713  bits<5> Rd;
2714  bits<5> Rn;
2715  bits<5> Rm;
2716  bits<6> extend;
2717  let Inst{30}    = isSub;
2718  let Inst{29}    = setFlags;
2719  let Inst{28-24} = 0b01011;
2720  let Inst{23-21} = 0b001;
2721  let Inst{20-16} = Rm;
2722  let Inst{15-13} = extend{5-3};
2723  let Inst{12-10} = extend{2-0};
2724  let Inst{9-5}   = Rn;
2725  let Inst{4-0}   = Rd;
2726
2727  let DecoderMethod = "DecodeAddSubERegInstruction";
2728}
2729
2730let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2731class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2732                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2733                       Operand ext_op, string asm>
2734    : I<(outs dstRegtype:$Rd),
2735        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2736        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2737      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2738  bits<5> Rd;
2739  bits<5> Rn;
2740  bits<5> Rm;
2741  bits<6> ext;
2742  let Inst{30}    = isSub;
2743  let Inst{29}    = setFlags;
2744  let Inst{28-24} = 0b01011;
2745  let Inst{23-21} = 0b001;
2746  let Inst{20-16} = Rm;
2747  let Inst{15}    = ext{5};
2748  let Inst{12-10} = ext{2-0};
2749  let Inst{9-5}   = Rn;
2750  let Inst{4-0}   = Rd;
2751
2752  let DecoderMethod = "DecodeAddSubERegInstruction";
2753}
2754
2755// Aliases for register+register add/subtract.
2756class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2757                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2758                     int shiftExt>
2759    : InstAlias<asm#"\t$dst, $src1, $src2",
2760                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2761                      shiftExt)>;
2762
2763multiclass AddSub<bit isSub, string mnemonic, string alias,
2764                  SDPatternOperator OpNode = null_frag> {
2765  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2766  // Add/Subtract immediate
2767  // Increase the weight of the immediate variant to try to match it before
2768  // the extended register variant.
2769  // We used to match the register variant before the immediate when the
2770  // register argument could be implicitly zero-extended.
2771  let AddedComplexity = 6 in
2772  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2773                           mnemonic, OpNode> {
2774    let Inst{31} = 0;
2775  }
2776  let AddedComplexity = 6 in
2777  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2778                           mnemonic, OpNode> {
2779    let Inst{31} = 1;
2780  }
2781
2782  // Add/Subtract register - Only used for CodeGen
2783  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2784  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2785
2786  // Add/Subtract shifted register
2787  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2788                           OpNode> {
2789    let Inst{31} = 0;
2790  }
2791  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2792                           OpNode> {
2793    let Inst{31} = 1;
2794  }
2795  }
2796
2797  // Add/Subtract extended register
2798  let AddedComplexity = 1, hasSideEffects = 0 in {
2799  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2800                           arith_extended_reg32_i32, mnemonic, OpNode> {
2801    let Inst{31} = 0;
2802  }
2803  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2804                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2805    let Inst{31} = 1;
2806  }
2807  }
2808
2809  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2810                               arith_extendlsl64, mnemonic> {
2811    // UXTX and SXTX only.
2812    let Inst{14-13} = 0b11;
2813    let Inst{31} = 1;
2814  }
2815
2816  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2817  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2818                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2819                      addsub_shifted_imm32_neg:$imm), 0>;
2820  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2821                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2822                       addsub_shifted_imm64_neg:$imm), 0>;
2823
2824  // Register/register aliases with no shift when SP is not used.
2825  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2826                       GPR32, GPR32, GPR32, 0>;
2827  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2828                       GPR64, GPR64, GPR64, 0>;
2829
2830  // Register/register aliases with no shift when either the destination or
2831  // first source register is SP.
2832  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2833                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2834  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2835                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2836  def : AddSubRegAlias<mnemonic,
2837                       !cast<Instruction>(NAME#"Xrx64"),
2838                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2839  def : AddSubRegAlias<mnemonic,
2840                       !cast<Instruction>(NAME#"Xrx64"),
2841                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2842}
2843
2844multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2845                   string alias, string cmpAlias> {
2846  let isCompare = 1, Defs = [NZCV] in {
2847  // Add/Subtract immediate
2848  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2849                           mnemonic, OpNode> {
2850    let Inst{31} = 0;
2851  }
2852  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2853                           mnemonic, OpNode> {
2854    let Inst{31} = 1;
2855  }
2856
2857  // Add/Subtract register
2858  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2859  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2860
2861  // Add/Subtract shifted register
2862  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2863                           OpNode> {
2864    let Inst{31} = 0;
2865  }
2866  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2867                           OpNode> {
2868    let Inst{31} = 1;
2869  }
2870
2871  // Add/Subtract extended register
2872  let AddedComplexity = 1 in {
2873  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2874                           arith_extended_reg32_i32, mnemonic, OpNode> {
2875    let Inst{31} = 0;
2876  }
2877  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2878                           arith_extended_reg32_i64, mnemonic, OpNode> {
2879    let Inst{31} = 1;
2880  }
2881  }
2882
2883  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2884                               arith_extendlsl64, mnemonic> {
2885    // UXTX and SXTX only.
2886    let Inst{14-13} = 0b11;
2887    let Inst{31} = 1;
2888  }
2889  } // Defs = [NZCV]
2890
2891  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2892  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2893                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2894                      addsub_shifted_imm32_neg:$imm), 0>;
2895  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2896                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2897                       addsub_shifted_imm64_neg:$imm), 0>;
2898
2899  // Compare aliases
2900  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2901                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2902  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2903                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2904  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2905                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2906  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2907                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2908  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2909                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2910  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2911                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2912  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2913                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2914
2915  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2916  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2917                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2918  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2919                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2920
2921  // Compare shorthands
2922  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2923                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2924  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2925                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2926  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2927                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2928  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2929                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2930
2931  // Register/register aliases with no shift when SP is not used.
2932  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2933                       GPR32, GPR32, GPR32, 0>;
2934  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2935                       GPR64, GPR64, GPR64, 0>;
2936
2937  // Register/register aliases with no shift when the first source register
2938  // is SP.
2939  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2940                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2941  def : AddSubRegAlias<mnemonic,
2942                       !cast<Instruction>(NAME#"Xrx64"),
2943                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2944}
2945
2946class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2947      : BaseAddSubImm<
2948          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2949          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2950          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2951  bits<6> imm6;
2952  bits<4> imm4;
2953  let Inst{31} = 1;
2954  let Inst{23-22} = 0b10;
2955  let Inst{21-16} = imm6;
2956  let Inst{15-14} = 0b00;
2957  let Inst{13-10} = imm4;
2958  let Unpredictable{15-14} = 0b11;
2959}
2960
2961class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2962      : BaseTwoOperandRegReg<0b1, setsFlags, 0b000000, GPR64, asm_instr, OpNode,
2963                             GPR64sp, GPR64sp>;
2964
2965//---
2966// Extract
2967//---
2968def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2969                                      SDTCisPtrTy<3>]>;
2970def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2971
2972class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2973                     list<dag> patterns>
2974    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2975         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2976      Sched<[WriteExtr, ReadExtrHi]> {
2977  bits<5> Rd;
2978  bits<5> Rn;
2979  bits<5> Rm;
2980  bits<6> imm;
2981
2982  let Inst{30-23} = 0b00100111;
2983  let Inst{21}    = 0;
2984  let Inst{20-16} = Rm;
2985  let Inst{15-10} = imm;
2986  let Inst{9-5}   = Rn;
2987  let Inst{4-0}   = Rd;
2988}
2989
2990multiclass ExtractImm<string asm> {
2991  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2992                      [(set GPR32:$Rd,
2993                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2994    let Inst{31} = 0;
2995    let Inst{22} = 0;
2996    // imm<5> must be zero.
2997    let imm{5}   = 0;
2998  }
2999  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
3000                      [(set GPR64:$Rd,
3001                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
3002
3003    let Inst{31} = 1;
3004    let Inst{22} = 1;
3005  }
3006}
3007
3008//---
3009// Bitfield
3010//---
3011
3012let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3013class BaseBitfieldImm<bits<2> opc,
3014                      RegisterClass regtype, Operand imm_type, string asm>
3015    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
3016         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
3017      Sched<[WriteIS, ReadI]> {
3018  bits<5> Rd;
3019  bits<5> Rn;
3020  bits<6> immr;
3021  bits<6> imms;
3022
3023  let Inst{30-29} = opc;
3024  let Inst{28-23} = 0b100110;
3025  let Inst{21-16} = immr;
3026  let Inst{15-10} = imms;
3027  let Inst{9-5}   = Rn;
3028  let Inst{4-0}   = Rd;
3029}
3030
3031multiclass BitfieldImm<bits<2> opc, string asm> {
3032  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
3033    let Inst{31} = 0;
3034    let Inst{22} = 0;
3035    // imms<5> and immr<5> must be zero, else ReservedValue().
3036    let Inst{21} = 0;
3037    let Inst{15} = 0;
3038  }
3039  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
3040    let Inst{31} = 1;
3041    let Inst{22} = 1;
3042  }
3043}
3044
3045let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3046class BaseBitfieldImmWith2RegArgs<bits<2> opc,
3047                      RegisterClass regtype, Operand imm_type, string asm>
3048    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
3049                             imm_type:$imms),
3050         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
3051      Sched<[WriteIS, ReadI]> {
3052  bits<5> Rd;
3053  bits<5> Rn;
3054  bits<6> immr;
3055  bits<6> imms;
3056
3057  let Inst{30-29} = opc;
3058  let Inst{28-23} = 0b100110;
3059  let Inst{21-16} = immr;
3060  let Inst{15-10} = imms;
3061  let Inst{9-5}   = Rn;
3062  let Inst{4-0}   = Rd;
3063}
3064
3065multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
3066  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
3067    let Inst{31} = 0;
3068    let Inst{22} = 0;
3069    // imms<5> and immr<5> must be zero, else ReservedValue().
3070    let Inst{21} = 0;
3071    let Inst{15} = 0;
3072  }
3073  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
3074    let Inst{31} = 1;
3075    let Inst{22} = 1;
3076  }
3077}
3078
3079//---
3080// Logical
3081//---
3082
3083// Logical (immediate)
3084class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
3085                     RegisterClass sregtype, Operand imm_type, string asm,
3086                     list<dag> pattern>
3087    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
3088         asm, "\t$Rd, $Rn, $imm", "", pattern>,
3089      Sched<[WriteI, ReadI]> {
3090  bits<5>  Rd;
3091  bits<5>  Rn;
3092  bits<13> imm;
3093  let Inst{30-29} = opc;
3094  let Inst{28-23} = 0b100100;
3095  let Inst{22}    = imm{12};
3096  let Inst{21-16} = imm{11-6};
3097  let Inst{15-10} = imm{5-0};
3098  let Inst{9-5}   = Rn;
3099  let Inst{4-0}   = Rd;
3100
3101  let DecoderMethod = "DecodeLogicalImmInstruction";
3102}
3103
3104// Logical (shifted register)
3105class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
3106                      logical_shifted_reg shifted_regtype, string asm,
3107                      list<dag> pattern>
3108    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
3109        asm, "\t$Rd, $Rn, $Rm_and_shift", "", pattern>,
3110      Sched<[WriteISReg, ReadI, ReadISReg]> {
3111  bits<5> Rd;
3112  bits<5> Rn;
3113  bits<5> Rm;
3114  bits<8> shift;
3115  let Inst{30-29} = opc;
3116  let Inst{28-24} = 0b01010;
3117  let Inst{23-22} = shift{7-6};
3118  let Inst{21}    = N;
3119  let Inst{20-16} = Rm;
3120  let Inst{15-10} = shift{5-0};
3121  let Inst{9-5}   = Rn;
3122  let Inst{4-0}   = Rd;
3123
3124  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
3125}
3126
3127// Aliases for register+register logical instructions.
3128class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
3129    : InstAlias<asm#"\t$dst, $src1, $src2",
3130                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
3131
3132multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
3133                      string Alias> {
3134  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3135  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
3136                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
3137                                               logical_imm32:$imm))]> {
3138    let Inst{31} = 0;
3139    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3140  }
3141  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3142  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
3143                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
3144                                               logical_imm64:$imm))]> {
3145    let Inst{31} = 1;
3146  }
3147
3148  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3149                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
3150                      logical_imm32_not:$imm), 0>;
3151  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3152                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
3153                       logical_imm64_not:$imm), 0>;
3154}
3155
3156multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
3157                       string Alias> {
3158  let isCompare = 1, Defs = [NZCV] in {
3159  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
3160      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
3161    let Inst{31} = 0;
3162    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3163  }
3164  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
3165      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
3166    let Inst{31} = 1;
3167  }
3168  } // end Defs = [NZCV]
3169
3170  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3171                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
3172                      logical_imm32_not:$imm), 0>;
3173  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3174                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
3175                       logical_imm64_not:$imm), 0>;
3176}
3177
3178class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
3179    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3180             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
3181      Sched<[WriteI, ReadI, ReadI]>;
3182
3183// Split from LogicalImm as not all instructions have both.
3184multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
3185                      SDPatternOperator OpNode, int AddedComplexityVal = 0> {
3186  let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = AddedComplexityVal in {
3187  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3188  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3189  }
3190
3191  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3192                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3193                                                 logical_shifted_reg32:$Rm_and_shift))]> {
3194    let Inst{31} = 0;
3195  }
3196  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3197                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3198                                                 logical_shifted_reg64:$Rm_and_shift))]> {
3199    let Inst{31} = 1;
3200  }
3201
3202  def : LogicalRegAlias<mnemonic,
3203                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3204  def : LogicalRegAlias<mnemonic,
3205                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3206}
3207
3208// Split from LogicalReg to allow setting NZCV Defs
3209multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3210                       SDPatternOperator OpNode = null_frag> {
3211  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3212  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3213  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3214
3215  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3216            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm_and_shift))]> {
3217    let Inst{31} = 0;
3218  }
3219  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3220            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm_and_shift))]> {
3221    let Inst{31} = 1;
3222  }
3223  } // Defs = [NZCV]
3224
3225  def : LogicalRegAlias<mnemonic,
3226                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3227  def : LogicalRegAlias<mnemonic,
3228                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3229}
3230
3231//---
3232// Conditionally set flags
3233//---
3234
3235let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3236class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3237                            string mnemonic, SDNode OpNode>
3238    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3239         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3240         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3241                             (i32 imm:$cond), NZCV))]>,
3242      Sched<[WriteI, ReadI]> {
3243  let Uses = [NZCV];
3244  let Defs = [NZCV];
3245
3246  bits<5> Rn;
3247  bits<5> imm;
3248  bits<4> nzcv;
3249  bits<4> cond;
3250
3251  let Inst{30}    = op;
3252  let Inst{29-21} = 0b111010010;
3253  let Inst{20-16} = imm;
3254  let Inst{15-12} = cond;
3255  let Inst{11-10} = 0b10;
3256  let Inst{9-5}   = Rn;
3257  let Inst{4}     = 0b0;
3258  let Inst{3-0}   = nzcv;
3259}
3260
3261let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3262class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3263                            SDNode OpNode>
3264    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3265         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3266         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3267                             (i32 imm:$cond), NZCV))]>,
3268      Sched<[WriteI, ReadI, ReadI]> {
3269  let Uses = [NZCV];
3270  let Defs = [NZCV];
3271
3272  bits<5> Rn;
3273  bits<5> Rm;
3274  bits<4> nzcv;
3275  bits<4> cond;
3276
3277  let Inst{30}    = op;
3278  let Inst{29-21} = 0b111010010;
3279  let Inst{20-16} = Rm;
3280  let Inst{15-12} = cond;
3281  let Inst{11-10} = 0b00;
3282  let Inst{9-5}   = Rn;
3283  let Inst{4}     = 0b0;
3284  let Inst{3-0}   = nzcv;
3285}
3286
3287multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3288  // immediate operand variants
3289  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3290    let Inst{31} = 0;
3291  }
3292  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3293    let Inst{31} = 1;
3294  }
3295  // register operand variants
3296  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3297    let Inst{31} = 0;
3298  }
3299  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3300    let Inst{31} = 1;
3301  }
3302}
3303
3304//---
3305// Conditional select
3306//---
3307
3308class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3309    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3310         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3311         [(set regtype:$Rd,
3312               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3313      Sched<[WriteI, ReadI, ReadI]> {
3314  let Uses = [NZCV];
3315
3316  bits<5> Rd;
3317  bits<5> Rn;
3318  bits<5> Rm;
3319  bits<4> cond;
3320
3321  let Inst{30}    = op;
3322  let Inst{29-21} = 0b011010100;
3323  let Inst{20-16} = Rm;
3324  let Inst{15-12} = cond;
3325  let Inst{11-10} = op2;
3326  let Inst{9-5}   = Rn;
3327  let Inst{4-0}   = Rd;
3328}
3329
3330multiclass CondSelect<bit op, bits<2> op2, string asm> {
3331  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3332    let Inst{31} = 0;
3333  }
3334  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3335    let Inst{31} = 1;
3336  }
3337}
3338
3339class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3340                       PatFrag frag>
3341    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3342         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3343         [(set regtype:$Rd,
3344               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3345               (i32 imm:$cond), NZCV))]>,
3346      Sched<[WriteI, ReadI, ReadI]> {
3347  let Uses = [NZCV];
3348
3349  bits<5> Rd;
3350  bits<5> Rn;
3351  bits<5> Rm;
3352  bits<4> cond;
3353
3354  let Inst{30}    = op;
3355  let Inst{29-21} = 0b011010100;
3356  let Inst{20-16} = Rm;
3357  let Inst{15-12} = cond;
3358  let Inst{11-10} = op2;
3359  let Inst{9-5}   = Rn;
3360  let Inst{4-0}   = Rd;
3361}
3362
3363def inv_cond_XFORM : SDNodeXForm<imm, [{
3364  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3365  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3366                                   MVT::i32);
3367}]>;
3368
3369multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3370  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3371    let Inst{31} = 0;
3372  }
3373  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3374    let Inst{31} = 1;
3375  }
3376
3377  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3378            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3379                                           (inv_cond_XFORM imm:$cond))>;
3380
3381  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3382            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3383                                           (inv_cond_XFORM imm:$cond))>;
3384}
3385
3386//---
3387// Special Mask Value
3388//---
3389def maski8_or_more : Operand<i32>,
3390  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3391}
3392def maski16_or_more : Operand<i32>,
3393  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3394}
3395
3396
3397//---
3398// Load/store
3399//---
3400
3401// (unsigned immediate)
3402// Indexed for 8-bit registers. offset is in range [0,4095].
3403def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3404def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3405def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3406def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3407def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3408
3409// (unsigned immediate)
3410// Indexed for 8-bit registers. offset is in range [0,63].
3411def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3412def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3413def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3414def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3415
3416def gi_am_indexed8 :
3417    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3418    GIComplexPatternEquiv<am_indexed8>;
3419def gi_am_indexed16 :
3420    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3421    GIComplexPatternEquiv<am_indexed16>;
3422def gi_am_indexed32 :
3423    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3424    GIComplexPatternEquiv<am_indexed32>;
3425def gi_am_indexed64 :
3426    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3427    GIComplexPatternEquiv<am_indexed64>;
3428def gi_am_indexed128 :
3429    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3430    GIComplexPatternEquiv<am_indexed128>;
3431
3432class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3433  let Name = "UImm12Offset" # Scale;
3434  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3435  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3436  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3437}
3438
3439def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3440def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3441def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3442def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3443def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3444
3445class uimm12_scaled<int Scale> : Operand<i64> {
3446  let ParserMatchClass
3447   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3448  let EncoderMethod
3449   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3450  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3451}
3452
3453def uimm12s1 : uimm12_scaled<1>;
3454def uimm12s2 : uimm12_scaled<2>;
3455def uimm12s4 : uimm12_scaled<4>;
3456def uimm12s8 : uimm12_scaled<8>;
3457def uimm12s16 : uimm12_scaled<16>;
3458
3459class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3460                      string asm, list<dag> pattern>
3461    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3462  bits<5> Rt;
3463
3464  bits<5> Rn;
3465  bits<12> offset;
3466
3467  let Inst{31-30} = sz;
3468  let Inst{29-27} = 0b111;
3469  let Inst{26}    = V;
3470  let Inst{25-24} = 0b01;
3471  let Inst{23-22} = opc;
3472  let Inst{21-10} = offset;
3473  let Inst{9-5}   = Rn;
3474  let Inst{4-0}   = Rt;
3475
3476  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3477}
3478
3479multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3480                  Operand indextype, string asm, list<dag> pattern> {
3481  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3482  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3483                           (ins GPR64sp:$Rn, indextype:$offset),
3484                           asm, pattern>,
3485           Sched<[WriteLD]>;
3486
3487  def : InstAlias<asm # "\t$Rt, [$Rn]",
3488                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3489}
3490
3491multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3492             Operand indextype, string asm, list<dag> pattern> {
3493  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3494  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3495                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3496                           asm, pattern>,
3497           Sched<[WriteST]>;
3498
3499  def : InstAlias<asm # "\t$Rt, [$Rn]",
3500                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3501}
3502
3503// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3504// substitute zero-registers automatically.
3505//
3506// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3507//       into StoreUI.
3508multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3509             Operand indextype, string asm, list<dag> pattern> {
3510  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3511  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3512                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3513                           asm, pattern>,
3514           Sched<[WriteST]>;
3515
3516  def : InstAlias<asm # "\t$Rt, [$Rn]",
3517                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3518}
3519
3520def PrefetchOperand : AsmOperandClass {
3521  let Name = "Prefetch";
3522  let ParserMethod = "tryParsePrefetch";
3523}
3524def prfop : Operand<i32> {
3525  let PrintMethod = "printPrefetchOp";
3526  let ParserMatchClass = PrefetchOperand;
3527}
3528
3529let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3530class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3531    : BaseLoadStoreUI<sz, V, opc,
3532                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3533                      asm, pat>,
3534      Sched<[WriteLD]>;
3535
3536//---
3537// Load literal
3538//---
3539
3540// Load literal address: 19-bit immediate. The low two bits of the target
3541// offset are implied zero and so are not part of the immediate.
3542def am_ldrlit : Operand<iPTR> {
3543  let EncoderMethod = "getLoadLiteralOpValue";
3544  let DecoderMethod = "DecodePCRelLabel19";
3545  let PrintMethod = "printAlignedLabel";
3546  let ParserMatchClass = PCRelLabel19Operand;
3547  let OperandType = "OPERAND_PCREL";
3548}
3549
3550let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3551class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3552    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3553        asm, "\t$Rt, $label", "", pat>,
3554      Sched<[WriteLD]> {
3555  bits<5> Rt;
3556  bits<19> label;
3557  let Inst{31-30} = opc;
3558  let Inst{29-27} = 0b011;
3559  let Inst{26}    = V;
3560  let Inst{25-24} = 0b00;
3561  let Inst{23-5}  = label;
3562  let Inst{4-0}   = Rt;
3563}
3564
3565let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3566class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3567    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3568        asm, "\t$Rt, $label", "", pat>,
3569      Sched<[WriteLD]> {
3570  bits<5> Rt;
3571  bits<19> label;
3572  let Inst{31-30} = opc;
3573  let Inst{29-27} = 0b011;
3574  let Inst{26}    = V;
3575  let Inst{25-24} = 0b00;
3576  let Inst{23-5}  = label;
3577  let Inst{4-0}   = Rt;
3578}
3579
3580//---
3581// Load/store register offset
3582//---
3583
3584def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3585def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3586def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3587def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3588def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3589
3590def gi_ro_Xindexed8 :
3591    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3592    GIComplexPatternEquiv<ro_Xindexed8>;
3593def gi_ro_Xindexed16 :
3594    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3595    GIComplexPatternEquiv<ro_Xindexed16>;
3596def gi_ro_Xindexed32 :
3597    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3598    GIComplexPatternEquiv<ro_Xindexed32>;
3599def gi_ro_Xindexed64 :
3600    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3601    GIComplexPatternEquiv<ro_Xindexed64>;
3602def gi_ro_Xindexed128 :
3603    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3604    GIComplexPatternEquiv<ro_Xindexed128>;
3605
3606def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3607def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3608def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3609def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3610def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3611
3612def gi_ro_Windexed8 :
3613    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3614    GIComplexPatternEquiv<ro_Windexed8>;
3615def gi_ro_Windexed16 :
3616    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3617    GIComplexPatternEquiv<ro_Windexed16>;
3618def gi_ro_Windexed32 :
3619    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3620    GIComplexPatternEquiv<ro_Windexed32>;
3621def gi_ro_Windexed64 :
3622    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3623    GIComplexPatternEquiv<ro_Windexed64>;
3624def gi_ro_Windexed128 :
3625    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3626    GIComplexPatternEquiv<ro_Windexed128>;
3627
3628class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3629  let Name = "Mem" # Reg # "Extend" # Width;
3630  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3631  let RenderMethod = "addMemExtendOperands";
3632  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3633}
3634
3635def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3636  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3637  // the trivial shift.
3638  let RenderMethod = "addMemExtend8Operands";
3639}
3640def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3641def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3642def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3643def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3644
3645def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3646  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3647  // the trivial shift.
3648  let RenderMethod = "addMemExtend8Operands";
3649}
3650def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3651def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3652def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3653def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3654
3655class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3656        : Operand<i32> {
3657  let ParserMatchClass = ParserClass;
3658  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3659  let DecoderMethod = "DecodeMemExtend";
3660  let EncoderMethod = "getMemExtendOpValue";
3661  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3662}
3663
3664def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3665def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3666def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3667def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3668def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3669
3670def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3671def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3672def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3673def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3674def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3675
3676class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3677                  Operand wextend, Operand xextend>  {
3678  // CodeGen-level pattern covering the entire addressing mode.
3679  ComplexPattern Wpat = windex;
3680  ComplexPattern Xpat = xindex;
3681
3682  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3683  Operand Wext = wextend;
3684  Operand Xext = xextend;
3685}
3686
3687def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3688def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3689def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3690def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3691def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3692                       ro_Xextend128>;
3693
3694class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3695                   dag outs, list<dag> pat>
3696    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3697  bits<5> Rt;
3698  bits<5> Rn;
3699  bits<5> Rm;
3700  bits<2> extend;
3701  let Inst{31-30} = sz;
3702  let Inst{29-27} = 0b111;
3703  let Inst{26}    = V;
3704  let Inst{25-24} = 0b00;
3705  let Inst{23-22} = opc;
3706  let Inst{21}    = 1;
3707  let Inst{20-16} = Rm;
3708  let Inst{15}    = extend{1}; // sign extend Rm?
3709  let Inst{14}    = 1;
3710  let Inst{12}    = extend{0}; // do shift?
3711  let Inst{11-10} = 0b10;
3712  let Inst{9-5}   = Rn;
3713  let Inst{4-0}   = Rt;
3714}
3715
3716class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3717  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3718              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3719
3720multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3721                   string asm, ValueType Ty, SDPatternOperator loadop> {
3722  let AddedComplexity = 10 in
3723  def roW : LoadStore8RO<sz, V, opc, asm,
3724                 (outs regtype:$Rt),
3725                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3726                 [(set (Ty regtype:$Rt),
3727                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3728                                             ro_Wextend8:$extend)))]>,
3729           Sched<[WriteLDIdx, ReadAdrBase]> {
3730    let Inst{13} = 0b0;
3731  }
3732
3733  let AddedComplexity = 10 in
3734  def roX : LoadStore8RO<sz, V, opc, asm,
3735                 (outs regtype:$Rt),
3736                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3737                 [(set (Ty regtype:$Rt),
3738                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3739                                             ro_Xextend8:$extend)))]>,
3740           Sched<[WriteLDIdx, ReadAdrBase]> {
3741    let Inst{13} = 0b1;
3742  }
3743
3744  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3745}
3746
3747multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3748                    string asm, ValueType Ty, SDPatternOperator storeop> {
3749  let AddedComplexity = 10 in
3750  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3751                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3752                 [(storeop (Ty regtype:$Rt),
3753                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3754                                         ro_Wextend8:$extend))]>,
3755            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3756    let Inst{13} = 0b0;
3757  }
3758
3759  let AddedComplexity = 10 in
3760  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3761                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3762                 [(storeop (Ty regtype:$Rt),
3763                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3764                                         ro_Xextend8:$extend))]>,
3765            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3766    let Inst{13} = 0b1;
3767  }
3768
3769  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3770}
3771
3772class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3773                    dag outs, list<dag> pat>
3774    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3775  bits<5> Rt;
3776  bits<5> Rn;
3777  bits<5> Rm;
3778  bits<2> extend;
3779  let Inst{31-30} = sz;
3780  let Inst{29-27} = 0b111;
3781  let Inst{26}    = V;
3782  let Inst{25-24} = 0b00;
3783  let Inst{23-22} = opc;
3784  let Inst{21}    = 1;
3785  let Inst{20-16} = Rm;
3786  let Inst{15}    = extend{1}; // sign extend Rm?
3787  let Inst{14}    = 1;
3788  let Inst{12}    = extend{0}; // do shift?
3789  let Inst{11-10} = 0b10;
3790  let Inst{9-5}   = Rn;
3791  let Inst{4-0}   = Rt;
3792}
3793
3794multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3795                    string asm, ValueType Ty, SDPatternOperator loadop> {
3796  let AddedComplexity = 10 in
3797  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3798                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3799                 [(set (Ty regtype:$Rt),
3800                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3801                                              ro_Wextend16:$extend)))]>,
3802            Sched<[WriteLDIdx, ReadAdrBase]> {
3803    let Inst{13} = 0b0;
3804  }
3805
3806  let AddedComplexity = 10 in
3807  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3808                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3809                 [(set (Ty regtype:$Rt),
3810                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3811                                             ro_Xextend16:$extend)))]>,
3812            Sched<[WriteLDIdx, ReadAdrBase]> {
3813    let Inst{13} = 0b1;
3814  }
3815
3816  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3817}
3818
3819multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3820                     string asm, ValueType Ty, SDPatternOperator storeop> {
3821  let AddedComplexity = 10 in
3822  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3823                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3824                [(storeop (Ty regtype:$Rt),
3825                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3826                                         ro_Wextend16:$extend))]>,
3827           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3828    let Inst{13} = 0b0;
3829  }
3830
3831  let AddedComplexity = 10 in
3832  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3833                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3834                [(storeop (Ty regtype:$Rt),
3835                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3836                                         ro_Xextend16:$extend))]>,
3837           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3838    let Inst{13} = 0b1;
3839  }
3840
3841  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3842}
3843
3844class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3845                    dag outs, list<dag> pat>
3846    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3847  bits<5> Rt;
3848  bits<5> Rn;
3849  bits<5> Rm;
3850  bits<2> extend;
3851  let Inst{31-30} = sz;
3852  let Inst{29-27} = 0b111;
3853  let Inst{26}    = V;
3854  let Inst{25-24} = 0b00;
3855  let Inst{23-22} = opc;
3856  let Inst{21}    = 1;
3857  let Inst{20-16} = Rm;
3858  let Inst{15}    = extend{1}; // sign extend Rm?
3859  let Inst{14}    = 1;
3860  let Inst{12}    = extend{0}; // do shift?
3861  let Inst{11-10} = 0b10;
3862  let Inst{9-5}   = Rn;
3863  let Inst{4-0}   = Rt;
3864}
3865
3866multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3867                    string asm, ValueType Ty, SDPatternOperator loadop> {
3868  let AddedComplexity = 10 in
3869  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3870                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3871                 [(set (Ty regtype:$Rt),
3872                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3873                                              ro_Wextend32:$extend)))]>,
3874           Sched<[WriteLDIdx, ReadAdrBase]> {
3875    let Inst{13} = 0b0;
3876  }
3877
3878  let AddedComplexity = 10 in
3879  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3880                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3881                 [(set (Ty regtype:$Rt),
3882                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3883                                              ro_Xextend32:$extend)))]>,
3884           Sched<[WriteLDIdx, ReadAdrBase]> {
3885    let Inst{13} = 0b1;
3886  }
3887
3888  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3889}
3890
3891multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3892                     string asm, ValueType Ty, SDPatternOperator storeop> {
3893  let AddedComplexity = 10 in
3894  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3895                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3896                [(storeop (Ty regtype:$Rt),
3897                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3898                                         ro_Wextend32:$extend))]>,
3899            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3900    let Inst{13} = 0b0;
3901  }
3902
3903  let AddedComplexity = 10 in
3904  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3905                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3906                [(storeop (Ty regtype:$Rt),
3907                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3908                                        ro_Xextend32:$extend))]>,
3909            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3910    let Inst{13} = 0b1;
3911  }
3912
3913  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3914}
3915
3916class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3917                    dag outs, list<dag> pat>
3918    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3919  bits<5> Rt;
3920  bits<5> Rn;
3921  bits<5> Rm;
3922  bits<2> extend;
3923  let Inst{31-30} = sz;
3924  let Inst{29-27} = 0b111;
3925  let Inst{26}    = V;
3926  let Inst{25-24} = 0b00;
3927  let Inst{23-22} = opc;
3928  let Inst{21}    = 1;
3929  let Inst{20-16} = Rm;
3930  let Inst{15}    = extend{1}; // sign extend Rm?
3931  let Inst{14}    = 1;
3932  let Inst{12}    = extend{0}; // do shift?
3933  let Inst{11-10} = 0b10;
3934  let Inst{9-5}   = Rn;
3935  let Inst{4-0}   = Rt;
3936}
3937
3938multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3939                    string asm, ValueType Ty, SDPatternOperator loadop> {
3940  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3941  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3942                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3943                [(set (Ty regtype:$Rt),
3944                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3945                                             ro_Wextend64:$extend)))]>,
3946           Sched<[WriteLDIdx, ReadAdrBase]> {
3947    let Inst{13} = 0b0;
3948  }
3949
3950  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3951  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3952                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3953                 [(set (Ty regtype:$Rt),
3954                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3955                                              ro_Xextend64:$extend)))]>,
3956           Sched<[WriteLDIdx, ReadAdrBase]> {
3957    let Inst{13} = 0b1;
3958  }
3959
3960  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3961}
3962
3963multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3964                     string asm, ValueType Ty, SDPatternOperator storeop> {
3965  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3966  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
3967                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3968                [(storeop (Ty regtype:$Rt),
3969                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3970                                         ro_Wextend64:$extend))]>,
3971            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3972    let Inst{13} = 0b0;
3973  }
3974
3975  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3976  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
3977                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3978                [(storeop (Ty regtype:$Rt),
3979                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3980                                         ro_Xextend64:$extend))]>,
3981            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3982    let Inst{13} = 0b1;
3983  }
3984
3985  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3986}
3987
3988class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3989                     dag outs, list<dag> pat>
3990    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3991  bits<5> Rt;
3992  bits<5> Rn;
3993  bits<5> Rm;
3994  bits<2> extend;
3995  let Inst{31-30} = sz;
3996  let Inst{29-27} = 0b111;
3997  let Inst{26}    = V;
3998  let Inst{25-24} = 0b00;
3999  let Inst{23-22} = opc;
4000  let Inst{21}    = 1;
4001  let Inst{20-16} = Rm;
4002  let Inst{15}    = extend{1}; // sign extend Rm?
4003  let Inst{14}    = 1;
4004  let Inst{12}    = extend{0}; // do shift?
4005  let Inst{11-10} = 0b10;
4006  let Inst{9-5}   = Rn;
4007  let Inst{4-0}   = Rt;
4008}
4009
4010multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4011                     string asm, ValueType Ty, SDPatternOperator loadop> {
4012  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4013  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4014                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4015                 [(set (Ty regtype:$Rt),
4016                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
4017                                               ro_Wextend128:$extend)))]>,
4018            Sched<[WriteLDIdx, ReadAdrBase]> {
4019    let Inst{13} = 0b0;
4020  }
4021
4022  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4023  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4024                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4025                 [(set (Ty regtype:$Rt),
4026                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
4027                                               ro_Xextend128:$extend)))]>,
4028            Sched<[WriteLDIdx, ReadAdrBase]> {
4029    let Inst{13} = 0b1;
4030  }
4031
4032  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4033}
4034
4035multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4036                      string asm> {
4037  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4038  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
4039               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4040                []>,
4041            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4042    let Inst{13} = 0b0;
4043  }
4044
4045  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4046  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
4047               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4048                []>,
4049            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4050    let Inst{13} = 0b1;
4051  }
4052
4053  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4054}
4055
4056let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4057class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
4058                     string asm, list<dag> pat>
4059    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
4060      Sched<[WriteLD]> {
4061  bits<5> Rt;
4062  bits<5> Rn;
4063  bits<5> Rm;
4064  bits<2> extend;
4065  let Inst{31-30} = sz;
4066  let Inst{29-27} = 0b111;
4067  let Inst{26}    = V;
4068  let Inst{25-24} = 0b00;
4069  let Inst{23-22} = opc;
4070  let Inst{21}    = 1;
4071  let Inst{20-16} = Rm;
4072  let Inst{15}    = extend{1}; // sign extend Rm?
4073  let Inst{14}    = 1;
4074  let Inst{12}    = extend{0}; // do shift?
4075  let Inst{11-10} = 0b10;
4076  let Inst{9-5}   = Rn;
4077  let Inst{4-0}   = Rt;
4078  let DecoderMethod = "DecodePRFMRegInstruction";
4079  // PRFM (reg) aliases with RPRFM added to the base A64 instruction set. When
4080  // the decoder method returns Fail, the decoder should attempt to decode the
4081  // instruction as RPRFM.
4082  let hasCompleteDecoder = 0;
4083}
4084
4085multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
4086  def roW : BasePrefetchRO<sz, V, opc, (outs),
4087                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4088                asm, [(AArch64Prefetch timm:$Rt,
4089                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4090                                                    ro_Wextend64:$extend))]> {
4091    let Inst{13} = 0b0;
4092  }
4093
4094  def roX : BasePrefetchRO<sz, V, opc, (outs),
4095                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4096                asm,  [(AArch64Prefetch timm:$Rt,
4097                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4098                                                     ro_Xextend64:$extend))]> {
4099    let Inst{13} = 0b1;
4100  }
4101
4102  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
4103               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
4104                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
4105}
4106
4107//---
4108// Load/store unscaled immediate
4109//---
4110
4111def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
4112def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
4113def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
4114def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
4115def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
4116
4117def gi_am_unscaled8 :
4118    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
4119    GIComplexPatternEquiv<am_unscaled8>;
4120def gi_am_unscaled16 :
4121    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
4122    GIComplexPatternEquiv<am_unscaled16>;
4123def gi_am_unscaled32 :
4124    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
4125    GIComplexPatternEquiv<am_unscaled32>;
4126def gi_am_unscaled64 :
4127    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
4128    GIComplexPatternEquiv<am_unscaled64>;
4129def gi_am_unscaled128 :
4130    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
4131    GIComplexPatternEquiv<am_unscaled128>;
4132
4133
4134class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4135                           string asm, list<dag> pattern>
4136    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
4137  bits<5> Rt;
4138  bits<5> Rn;
4139  bits<9> offset;
4140  let Inst{31-30} = sz;
4141  let Inst{29-27} = 0b111;
4142  let Inst{26}    = V;
4143  let Inst{25-24} = 0b00;
4144  let Inst{23-22} = opc;
4145  let Inst{21}    = 0;
4146  let Inst{20-12} = offset;
4147  let Inst{11-10} = 0b00;
4148  let Inst{9-5}   = Rn;
4149  let Inst{4-0}   = Rt;
4150
4151  let DecoderMethod = "DecodeSignedLdStInstruction";
4152}
4153
4154// Armv8.4 LDAPR & STLR with Immediate Offset instruction
4155multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4156                              DAGOperand regtype > {
4157  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
4158                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
4159          Sched<[WriteST]> {
4160    let Inst{29} = 0;
4161    let Inst{24} = 1;
4162  }
4163  def : InstAlias<asm # "\t$Rt, [$Rn]",
4164                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4165}
4166
4167multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4168                               DAGOperand regtype > {
4169  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
4170                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4171                               asm, []>,
4172          Sched<[WriteST]> {
4173    let Inst{29} = 0;
4174    let Inst{24} = 1;
4175  }
4176  def : InstAlias<asm # "\t$Rt, [$Rn]",
4177                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4178}
4179
4180multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4181                   string asm, list<dag> pattern> {
4182  let AddedComplexity = 1 in // try this before LoadUI
4183  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
4184                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
4185          Sched<[WriteLD]>;
4186
4187  def : InstAlias<asm # "\t$Rt, [$Rn]",
4188                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4189}
4190
4191multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4192                         string asm, list<dag> pattern> {
4193  let AddedComplexity = 1 in // try this before StoreUI
4194  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4195                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4196                               asm, pattern>,
4197          Sched<[WriteST]>;
4198
4199  def : InstAlias<asm # "\t$Rt, [$Rn]",
4200                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4201}
4202
4203multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4204                            list<dag> pat> {
4205  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4206  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4207                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4208                               asm, pat>,
4209          Sched<[WriteLD]>;
4210
4211  def : InstAlias<asm # "\t$Rt, [$Rn]",
4212                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4213}
4214
4215//---
4216// Load/store unscaled immediate, unprivileged
4217//---
4218
4219class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4220                                dag oops, dag iops, string asm>
4221    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4222  bits<5> Rt;
4223  bits<5> Rn;
4224  bits<9> offset;
4225  let Inst{31-30} = sz;
4226  let Inst{29-27} = 0b111;
4227  let Inst{26}    = V;
4228  let Inst{25-24} = 0b00;
4229  let Inst{23-22} = opc;
4230  let Inst{21}    = 0;
4231  let Inst{20-12} = offset;
4232  let Inst{11-10} = 0b10;
4233  let Inst{9-5}   = Rn;
4234  let Inst{4-0}   = Rt;
4235
4236  let DecoderMethod = "DecodeSignedLdStInstruction";
4237}
4238
4239multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4240                            RegisterClass regtype, string asm> {
4241  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4242  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4243                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4244          Sched<[WriteLD]>;
4245
4246  def : InstAlias<asm # "\t$Rt, [$Rn]",
4247                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4248}
4249
4250multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4251                             RegisterClass regtype, string asm> {
4252  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4253  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4254                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4255                                 asm>,
4256          Sched<[WriteST]>;
4257
4258  def : InstAlias<asm # "\t$Rt, [$Rn]",
4259                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4260}
4261
4262//---
4263// Load/store pre-indexed
4264//---
4265
4266class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4267                          string asm, string cstr, list<dag> pat>
4268    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4269  bits<5> Rt;
4270  bits<5> Rn;
4271  bits<9> offset;
4272  let Inst{31-30} = sz;
4273  let Inst{29-27} = 0b111;
4274  let Inst{26}    = V;
4275  let Inst{25-24} = 0;
4276  let Inst{23-22} = opc;
4277  let Inst{21}    = 0;
4278  let Inst{20-12} = offset;
4279  let Inst{11-10} = 0b11;
4280  let Inst{9-5}   = Rn;
4281  let Inst{4-0}   = Rt;
4282
4283  let DecoderMethod = "DecodeSignedLdStInstruction";
4284}
4285
4286let hasSideEffects = 0 in {
4287let mayStore = 0, mayLoad = 1 in
4288class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4289             string asm>
4290    : BaseLoadStorePreIdx<sz, V, opc,
4291                     (outs GPR64sp:$wback, regtype:$Rt),
4292                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4293                     "$Rn = $wback,@earlyclobber $wback", []>,
4294      Sched<[WriteAdr, WriteLD]>;
4295
4296let mayStore = 1, mayLoad = 0 in
4297class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4298                  string asm, SDPatternOperator storeop, ValueType Ty>
4299    : BaseLoadStorePreIdx<sz, V, opc,
4300                      (outs GPR64sp:$wback),
4301                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4302                      asm, "$Rn = $wback,@earlyclobber $wback",
4303      [(set GPR64sp:$wback,
4304            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4305      Sched<[WriteAdr, WriteST]>;
4306} // hasSideEffects = 0
4307
4308//---
4309// Load/store post-indexed
4310//---
4311
4312class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4313                          string asm, string cstr, list<dag> pat>
4314    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4315  bits<5> Rt;
4316  bits<5> Rn;
4317  bits<9> offset;
4318  let Inst{31-30} = sz;
4319  let Inst{29-27} = 0b111;
4320  let Inst{26}    = V;
4321  let Inst{25-24} = 0b00;
4322  let Inst{23-22} = opc;
4323  let Inst{21}    = 0b0;
4324  let Inst{20-12} = offset;
4325  let Inst{11-10} = 0b01;
4326  let Inst{9-5}   = Rn;
4327  let Inst{4-0}   = Rt;
4328
4329  let DecoderMethod = "DecodeSignedLdStInstruction";
4330}
4331
4332let hasSideEffects = 0 in {
4333let mayStore = 0, mayLoad = 1 in
4334class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4335             string asm>
4336    : BaseLoadStorePostIdx<sz, V, opc,
4337                      (outs GPR64sp:$wback, regtype:$Rt),
4338                      (ins GPR64sp:$Rn, simm9:$offset),
4339                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4340      Sched<[WriteAdr, WriteLD]>;
4341
4342let mayStore = 1, mayLoad = 0 in
4343class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4344                   string asm, SDPatternOperator storeop, ValueType Ty>
4345    : BaseLoadStorePostIdx<sz, V, opc,
4346                      (outs GPR64sp:$wback),
4347                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4348                       asm, "$Rn = $wback,@earlyclobber $wback",
4349      [(set GPR64sp:$wback,
4350            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4351    Sched<[WriteAdr, WriteST]>;
4352} // hasSideEffects = 0
4353
4354
4355//---
4356// Load/store pair
4357//---
4358
4359// (indexed, offset)
4360
4361class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4362                              string asm>
4363    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4364  bits<5> Rt;
4365  bits<5> Rt2;
4366  bits<5> Rn;
4367  bits<7> offset;
4368  let Inst{31-30} = opc;
4369  let Inst{29-27} = 0b101;
4370  let Inst{26}    = V;
4371  let Inst{25-23} = 0b010;
4372  let Inst{22}    = L;
4373  let Inst{21-15} = offset;
4374  let Inst{14-10} = Rt2;
4375  let Inst{9-5}   = Rn;
4376  let Inst{4-0}   = Rt;
4377
4378  let DecoderMethod = "DecodePairLdStInstruction";
4379}
4380
4381multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4382                          Operand indextype, string asm> {
4383  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4384  def i : BaseLoadStorePairOffset<opc, V, 1,
4385                                  (outs regtype:$Rt, regtype:$Rt2),
4386                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4387          Sched<[WriteLD, WriteLDHi]>;
4388
4389  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4390                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4391                                                  GPR64sp:$Rn, 0)>;
4392}
4393
4394
4395multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4396                           Operand indextype, string asm> {
4397  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4398  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4399                                  (ins regtype:$Rt, regtype:$Rt2,
4400                                       GPR64sp:$Rn, indextype:$offset),
4401                                  asm>,
4402          Sched<[WriteSTP]>;
4403
4404  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4405                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4406                                                  GPR64sp:$Rn, 0)>;
4407}
4408
4409// (pre-indexed)
4410class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4411                              string asm>
4412    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4413  bits<5> Rt;
4414  bits<5> Rt2;
4415  bits<5> Rn;
4416  bits<7> offset;
4417  let Inst{31-30} = opc;
4418  let Inst{29-27} = 0b101;
4419  let Inst{26}    = V;
4420  let Inst{25-23} = 0b011;
4421  let Inst{22}    = L;
4422  let Inst{21-15} = offset;
4423  let Inst{14-10} = Rt2;
4424  let Inst{9-5}   = Rn;
4425  let Inst{4-0}   = Rt;
4426
4427  let DecoderMethod = "DecodePairLdStInstruction";
4428}
4429
4430let hasSideEffects = 0 in {
4431let mayStore = 0, mayLoad = 1 in
4432class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4433                     Operand indextype, string asm>
4434    : BaseLoadStorePairPreIdx<opc, V, 1,
4435                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4436                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4437      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4438
4439let mayStore = 1, mayLoad = 0 in
4440class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4441                      Operand indextype, string asm>
4442    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4443                             (ins regtype:$Rt, regtype:$Rt2,
4444                                  GPR64sp:$Rn, indextype:$offset),
4445                             asm>,
4446      Sched<[WriteAdr, WriteSTP]>;
4447} // hasSideEffects = 0
4448
4449// (post-indexed)
4450
4451class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4452                              string asm>
4453    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4454  bits<5> Rt;
4455  bits<5> Rt2;
4456  bits<5> Rn;
4457  bits<7> offset;
4458  let Inst{31-30} = opc;
4459  let Inst{29-27} = 0b101;
4460  let Inst{26}    = V;
4461  let Inst{25-23} = 0b001;
4462  let Inst{22}    = L;
4463  let Inst{21-15} = offset;
4464  let Inst{14-10} = Rt2;
4465  let Inst{9-5}   = Rn;
4466  let Inst{4-0}   = Rt;
4467
4468  let DecoderMethod = "DecodePairLdStInstruction";
4469}
4470
4471let hasSideEffects = 0 in {
4472let mayStore = 0, mayLoad = 1 in
4473class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4474                      Operand idxtype, string asm>
4475    : BaseLoadStorePairPostIdx<opc, V, 1,
4476                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4477                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4478      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4479
4480let mayStore = 1, mayLoad = 0 in
4481class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4482                       Operand idxtype, string asm>
4483    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4484                             (ins regtype:$Rt, regtype:$Rt2,
4485                                  GPR64sp:$Rn, idxtype:$offset),
4486                             asm>,
4487      Sched<[WriteAdr, WriteSTP]>;
4488} // hasSideEffects = 0
4489
4490//  (no-allocate)
4491
4492class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4493                              string asm>
4494    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4495  bits<5> Rt;
4496  bits<5> Rt2;
4497  bits<5> Rn;
4498  bits<7> offset;
4499  let Inst{31-30} = opc;
4500  let Inst{29-27} = 0b101;
4501  let Inst{26}    = V;
4502  let Inst{25-23} = 0b000;
4503  let Inst{22}    = L;
4504  let Inst{21-15} = offset;
4505  let Inst{14-10} = Rt2;
4506  let Inst{9-5}   = Rn;
4507  let Inst{4-0}   = Rt;
4508
4509  let DecoderMethod = "DecodePairLdStInstruction";
4510}
4511
4512multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4513                           Operand indextype, string asm> {
4514  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4515  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4516                                   (outs regtype:$Rt, regtype:$Rt2),
4517                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4518          Sched<[WriteLD, WriteLDHi]>;
4519
4520
4521  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4522                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4523                                                  GPR64sp:$Rn, 0)>;
4524}
4525
4526multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4527                      Operand indextype, string asm> {
4528  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4529  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4530                                   (ins regtype:$Rt, regtype:$Rt2,
4531                                        GPR64sp:$Rn, indextype:$offset),
4532                                   asm>,
4533          Sched<[WriteSTP]>;
4534
4535  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4536                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4537                                                  GPR64sp:$Rn, 0)>;
4538}
4539
4540//---
4541// Load/store exclusive
4542//---
4543
4544// True exclusive operations write to and/or read from the system's exclusive
4545// monitors, which as far as a compiler is concerned can be modelled as a
4546// random shared memory address. Hence LoadExclusive mayStore.
4547//
4548// Since these instructions have the undefined register bits set to 1 in
4549// their canonical form, we need a post encoder method to set those bits
4550// to 1 when encoding these instructions. We do this using the
4551// fixLoadStoreExclusive function. This function has template parameters:
4552//
4553// fixLoadStoreExclusive<int hasRs, int hasRt2>
4554//
4555// hasRs indicates that the instruction uses the Rs field, so we won't set
4556// it to 1 (and the same for Rt2). We don't need template parameters for
4557// the other register fields since Rt and Rn are always used.
4558//
4559let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4560class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4561                             dag oops, dag iops, string asm, string operands>
4562    : I<oops, iops, asm, operands, "", []> {
4563  let Inst{31-30} = sz;
4564  let Inst{29-24} = 0b001000;
4565  let Inst{23}    = o2;
4566  let Inst{22}    = L;
4567  let Inst{21}    = o1;
4568  let Inst{15}    = o0;
4569
4570  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4571}
4572
4573// Neither Rs nor Rt2 operands.
4574class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4575                               dag oops, dag iops, string asm, string operands>
4576    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4577  bits<5> Rt;
4578  bits<5> Rn;
4579  let Inst{20-16} = 0b11111;
4580  let Unpredictable{20-16} = 0b11111;
4581  let Inst{14-10} = 0b11111;
4582  let Unpredictable{14-10} = 0b11111;
4583  let Inst{9-5} = Rn;
4584  let Inst{4-0} = Rt;
4585
4586  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4587}
4588
4589// Simple load acquires don't set the exclusive monitor
4590let mayLoad = 1, mayStore = 0 in
4591class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4592                  RegisterClass regtype, string asm>
4593    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4594                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4595      Sched<[WriteLD]>;
4596
4597class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4598                    RegisterClass regtype, string asm>
4599    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4600                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4601      Sched<[WriteLD]>;
4602
4603class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4604                       RegisterClass regtype, string asm>
4605    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4606                             (outs regtype:$Rt, regtype:$Rt2),
4607                             (ins GPR64sp0:$Rn), asm,
4608                             "\t$Rt, $Rt2, [$Rn]">,
4609      Sched<[WriteLD, WriteLDHi]> {
4610  bits<5> Rt;
4611  bits<5> Rt2;
4612  bits<5> Rn;
4613  let Inst{14-10} = Rt2;
4614  let Inst{9-5} = Rn;
4615  let Inst{4-0} = Rt;
4616
4617  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4618}
4619
4620// Simple store release operations do not check the exclusive monitor.
4621let mayLoad = 0, mayStore = 1 in
4622class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4623                   RegisterClass regtype, string asm>
4624    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4625                               (ins regtype:$Rt, GPR64sp:$Rn),
4626                               asm, "\t$Rt, [$Rn]">,
4627      Sched<[WriteST]>;
4628
4629let mayLoad = 1, mayStore = 1 in
4630class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4631                     RegisterClass regtype, string asm>
4632    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4633                             (ins regtype:$Rt, GPR64sp0:$Rn),
4634                             asm, "\t$Ws, $Rt, [$Rn]">,
4635      Sched<[WriteSTX]> {
4636  bits<5> Ws;
4637  bits<5> Rt;
4638  bits<5> Rn;
4639  let Inst{20-16} = Ws;
4640  let Inst{9-5} = Rn;
4641  let Inst{4-0} = Rt;
4642
4643  let Constraints = "@earlyclobber $Ws";
4644  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4645}
4646
4647class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4648                         RegisterClass regtype, string asm>
4649    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4650                             (outs GPR32:$Ws),
4651                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4652                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4653      Sched<[WriteSTX]> {
4654  bits<5> Ws;
4655  bits<5> Rt;
4656  bits<5> Rt2;
4657  bits<5> Rn;
4658  let Inst{20-16} = Ws;
4659  let Inst{14-10} = Rt2;
4660  let Inst{9-5} = Rn;
4661  let Inst{4-0} = Rt;
4662
4663  let Constraints = "@earlyclobber $Ws";
4664}
4665
4666// Armv8.5-A Memory Tagging Extension
4667class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4668                 string asm_opnds, string cstr, dag oops, dag iops>
4669    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4670      Sched<[]> {
4671  bits<5> Rn;
4672
4673  let Inst{31-24} = 0b11011001;
4674  let Inst{23-22} = opc1;
4675  let Inst{21}    = 1;
4676  // Inst{20-12} defined by subclass
4677  let Inst{11-10} = opc2;
4678  let Inst{9-5}   = Rn;
4679  // Inst{4-0} defined by subclass
4680}
4681
4682class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4683                   dag oops, dag iops>
4684    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4685                  "", oops, iops> {
4686  bits<5> Rt;
4687
4688  let Inst{20-12} = 0b000000000;
4689  let Inst{4-0}   = Rt;
4690
4691  let mayLoad = Load;
4692}
4693
4694class MemTagLoad<string asm_insn, string asm_opnds>
4695    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4696                 (outs GPR64:$wback),
4697                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4698  bits<5> Rt;
4699  bits<9> offset;
4700
4701  let Inst{20-12} = offset;
4702  let Inst{4-0}   = Rt;
4703
4704  let mayLoad = 1;
4705}
4706
4707class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4708                     string asm_opnds, string cstr, dag oops, dag iops>
4709    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4710  bits<5> Rt;
4711  bits<9> offset;
4712
4713  let Inst{20-12} = offset;
4714  let Inst{4-0}   = Rt;
4715
4716  let mayStore = 1;
4717}
4718
4719multiclass MemTagStore<bits<2> opc1, string insn> {
4720  def i :
4721    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4722                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4723  def PreIndex :
4724    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4725                    "$Rn = $wback",
4726                    (outs GPR64sp:$wback),
4727                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4728  def PostIndex :
4729    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4730                    "$Rn = $wback",
4731                    (outs GPR64sp:$wback),
4732                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4733
4734  def : InstAlias<insn # "\t$Rt, [$Rn]",
4735                  (!cast<Instruction>(NAME # "i") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4736}
4737
4738//---
4739// Exception generation
4740//---
4741
4742let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4743class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4744                          list<dag> pattern = []>
4745    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4746      Sched<[WriteSys]> {
4747  bits<16> imm;
4748  let Inst{31-24} = 0b11010100;
4749  let Inst{23-21} = op1;
4750  let Inst{20-5}  = imm;
4751  let Inst{4-2}   = 0b000;
4752  let Inst{1-0}   = ll;
4753}
4754
4755//---
4756// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4757//--
4758let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4759class UDFType<bits<16> opc, string asm>
4760  : I<(outs), (ins uimm16:$imm),
4761       asm, "\t$imm", "", []>,
4762    Sched<[]> {
4763  bits<16> imm;
4764  let Inst{31-16} = opc;
4765  let Inst{15-0} = imm;
4766}
4767}
4768let Predicates = [HasFPARMv8] in {
4769
4770//---
4771// Floating point to integer conversion
4772//---
4773
4774let mayRaiseFPException = 1, Uses = [FPCR] in
4775class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4776                      RegisterClass srcType, RegisterClass dstType,
4777                      string asm, list<dag> pattern>
4778    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4779         asm, "\t$Rd, $Rn", "", pattern>,
4780      Sched<[WriteFCvt]> {
4781  bits<5> Rd;
4782  bits<5> Rn;
4783  let Inst{30-29} = 0b00;
4784  let Inst{28-24} = 0b11110;
4785  let Inst{23-22} = type;
4786  let Inst{21}    = 1;
4787  let Inst{20-19} = rmode;
4788  let Inst{18-16} = opcode;
4789  let Inst{15-10} = 0;
4790  let Inst{9-5}   = Rn;
4791  let Inst{4-0}   = Rd;
4792}
4793
4794let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4795class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4796                      RegisterClass srcType, RegisterClass dstType,
4797                      Operand immType, string asm, list<dag> pattern>
4798    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4799         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4800      Sched<[WriteFCvt]> {
4801  bits<5> Rd;
4802  bits<5> Rn;
4803  bits<6> scale;
4804  let Inst{30-29} = 0b00;
4805  let Inst{28-24} = 0b11110;
4806  let Inst{23-22} = type;
4807  let Inst{21}    = 0;
4808  let Inst{20-19} = rmode;
4809  let Inst{18-16} = opcode;
4810  let Inst{15-10} = scale;
4811  let Inst{9-5}   = Rn;
4812  let Inst{4-0}   = Rd;
4813}
4814
4815multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4816           SDPatternOperator OpN> {
4817  // Unscaled half-precision to 32-bit
4818  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4819                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4820    let Inst{31} = 0; // 32-bit GPR flag
4821    let Predicates = [HasFullFP16];
4822  }
4823
4824  // Unscaled half-precision to 64-bit
4825  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4826                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4827    let Inst{31} = 1; // 64-bit GPR flag
4828    let Predicates = [HasFullFP16];
4829  }
4830
4831  // Unscaled single-precision to 32-bit
4832  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4833                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4834    let Inst{31} = 0; // 32-bit GPR flag
4835  }
4836
4837  // Unscaled single-precision to 64-bit
4838  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4839                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4840    let Inst{31} = 1; // 64-bit GPR flag
4841  }
4842
4843  // Unscaled double-precision to 32-bit
4844  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4845                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4846    let Inst{31} = 0; // 32-bit GPR flag
4847  }
4848
4849  // Unscaled double-precision to 64-bit
4850  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4851                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4852    let Inst{31} = 1; // 64-bit GPR flag
4853  }
4854}
4855
4856multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4857                             SDPatternOperator OpN> {
4858  // Scaled half-precision to 32-bit
4859  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4860                              fixedpoint_f16_i32, asm,
4861              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4862                                          fixedpoint_f16_i32:$scale)))]> {
4863    let Inst{31} = 0; // 32-bit GPR flag
4864    let scale{5} = 1;
4865    let Predicates = [HasFullFP16];
4866  }
4867
4868  // Scaled half-precision to 64-bit
4869  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4870                              fixedpoint_f16_i64, asm,
4871              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4872                                          fixedpoint_f16_i64:$scale)))]> {
4873    let Inst{31} = 1; // 64-bit GPR flag
4874    let Predicates = [HasFullFP16];
4875  }
4876
4877  // Scaled single-precision to 32-bit
4878  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4879                              fixedpoint_f32_i32, asm,
4880              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4881                                          fixedpoint_f32_i32:$scale)))]> {
4882    let Inst{31} = 0; // 32-bit GPR flag
4883    let scale{5} = 1;
4884  }
4885
4886  // Scaled single-precision to 64-bit
4887  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4888                              fixedpoint_f32_i64, asm,
4889              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4890                                          fixedpoint_f32_i64:$scale)))]> {
4891    let Inst{31} = 1; // 64-bit GPR flag
4892  }
4893
4894  // Scaled double-precision to 32-bit
4895  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4896                              fixedpoint_f64_i32, asm,
4897              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4898                                          fixedpoint_f64_i32:$scale)))]> {
4899    let Inst{31} = 0; // 32-bit GPR flag
4900    let scale{5} = 1;
4901  }
4902
4903  // Scaled double-precision to 64-bit
4904  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4905                              fixedpoint_f64_i64, asm,
4906              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4907                                          fixedpoint_f64_i64:$scale)))]> {
4908    let Inst{31} = 1; // 64-bit GPR flag
4909  }
4910}
4911
4912//---
4913// Integer to floating point conversion
4914//---
4915
4916let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4917class BaseIntegerToFP<bit isUnsigned,
4918                      RegisterClass srcType, RegisterClass dstType,
4919                      Operand immType, string asm, list<dag> pattern>
4920    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4921         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4922      Sched<[WriteFCvt]> {
4923  bits<5> Rd;
4924  bits<5> Rn;
4925  bits<6> scale;
4926  let Inst{30-24} = 0b0011110;
4927  let Inst{21-17} = 0b00001;
4928  let Inst{16}    = isUnsigned;
4929  let Inst{15-10} = scale;
4930  let Inst{9-5}   = Rn;
4931  let Inst{4-0}   = Rd;
4932}
4933
4934let mayRaiseFPException = 1, Uses = [FPCR] in
4935class BaseIntegerToFPUnscaled<bit isUnsigned,
4936                      RegisterClass srcType, RegisterClass dstType,
4937                      ValueType dvt, string asm, SDPatternOperator node>
4938    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4939         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4940      Sched<[WriteFCvt]> {
4941  bits<5> Rd;
4942  bits<5> Rn;
4943  bits<6> scale;
4944  let Inst{30-24} = 0b0011110;
4945  let Inst{21-17} = 0b10001;
4946  let Inst{16}    = isUnsigned;
4947  let Inst{15-10} = 0b000000;
4948  let Inst{9-5}   = Rn;
4949  let Inst{4-0}   = Rd;
4950}
4951
4952multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4953  // Unscaled
4954  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4955    let Inst{31} = 0; // 32-bit GPR flag
4956    let Inst{23-22} = 0b11; // 16-bit FPR flag
4957    let Predicates = [HasFullFP16];
4958  }
4959
4960  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4961    let Inst{31} = 0; // 32-bit GPR flag
4962    let Inst{23-22} = 0b00; // 32-bit FPR flag
4963  }
4964
4965  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4966    let Inst{31} = 0; // 32-bit GPR flag
4967    let Inst{23-22} = 0b01; // 64-bit FPR flag
4968  }
4969
4970  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4971    let Inst{31} = 1; // 64-bit GPR flag
4972    let Inst{23-22} = 0b11; // 16-bit FPR flag
4973    let Predicates = [HasFullFP16];
4974  }
4975
4976  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4977    let Inst{31} = 1; // 64-bit GPR flag
4978    let Inst{23-22} = 0b00; // 32-bit FPR flag
4979  }
4980
4981  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4982    let Inst{31} = 1; // 64-bit GPR flag
4983    let Inst{23-22} = 0b01; // 64-bit FPR flag
4984  }
4985
4986  // Scaled
4987  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4988                             [(set (f16 FPR16:$Rd),
4989                                   (fdiv (node GPR32:$Rn),
4990                                         fixedpoint_f16_i32:$scale))]> {
4991    let Inst{31} = 0; // 32-bit GPR flag
4992    let Inst{23-22} = 0b11; // 16-bit FPR flag
4993    let scale{5} = 1;
4994    let Predicates = [HasFullFP16];
4995  }
4996
4997  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4998                             [(set FPR32:$Rd,
4999                                   (fdiv (node GPR32:$Rn),
5000                                         fixedpoint_f32_i32:$scale))]> {
5001    let Inst{31} = 0; // 32-bit GPR flag
5002    let Inst{23-22} = 0b00; // 32-bit FPR flag
5003    let scale{5} = 1;
5004  }
5005
5006  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
5007                             [(set FPR64:$Rd,
5008                                   (fdiv (node GPR32:$Rn),
5009                                         fixedpoint_f64_i32:$scale))]> {
5010    let Inst{31} = 0; // 32-bit GPR flag
5011    let Inst{23-22} = 0b01; // 64-bit FPR flag
5012    let scale{5} = 1;
5013  }
5014
5015  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
5016                             [(set (f16 FPR16:$Rd),
5017                                   (fdiv (node GPR64:$Rn),
5018                                         fixedpoint_f16_i64:$scale))]> {
5019    let Inst{31} = 1; // 64-bit GPR flag
5020    let Inst{23-22} = 0b11; // 16-bit FPR flag
5021    let Predicates = [HasFullFP16];
5022  }
5023
5024  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
5025                             [(set FPR32:$Rd,
5026                                   (fdiv (node GPR64:$Rn),
5027                                         fixedpoint_f32_i64:$scale))]> {
5028    let Inst{31} = 1; // 64-bit GPR flag
5029    let Inst{23-22} = 0b00; // 32-bit FPR flag
5030  }
5031
5032  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
5033                             [(set FPR64:$Rd,
5034                                   (fdiv (node GPR64:$Rn),
5035                                         fixedpoint_f64_i64:$scale))]> {
5036    let Inst{31} = 1; // 64-bit GPR flag
5037    let Inst{23-22} = 0b01; // 64-bit FPR flag
5038  }
5039}
5040
5041//---
5042// Unscaled integer <-> floating point conversion (i.e. FMOV)
5043//---
5044
5045let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5046class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
5047                      RegisterClass srcType, RegisterClass dstType,
5048                      string asm>
5049    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
5050        // We use COPY_TO_REGCLASS for these bitconvert operations.
5051        // copyPhysReg() expands the resultant COPY instructions after
5052        // regalloc is done. This gives greater freedom for the allocator
5053        // and related passes (coalescing, copy propagation, et. al.) to
5054        // be more effective.
5055        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
5056      Sched<[WriteFCopy]> {
5057  bits<5> Rd;
5058  bits<5> Rn;
5059  let Inst{30-24} = 0b0011110;
5060  let Inst{21}    = 1;
5061  let Inst{20-19} = rmode;
5062  let Inst{18-16} = opcode;
5063  let Inst{15-10} = 0b000000;
5064  let Inst{9-5}   = Rn;
5065  let Inst{4-0}   = Rd;
5066}
5067
5068let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5069class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
5070                     RegisterClass srcType, RegisterOperand dstType, string asm,
5071                     string kind>
5072    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5073        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
5074      Sched<[WriteFCopy]> {
5075  bits<5> Rd;
5076  bits<5> Rn;
5077  let Inst{30-23} = 0b00111101;
5078  let Inst{21}    = 1;
5079  let Inst{20-19} = rmode;
5080  let Inst{18-16} = opcode;
5081  let Inst{15-10} = 0b000000;
5082  let Inst{9-5}   = Rn;
5083  let Inst{4-0}   = Rd;
5084
5085  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5086}
5087
5088let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5089class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
5090                     RegisterOperand srcType, RegisterClass dstType, string asm,
5091                     string kind>
5092    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5093        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
5094      Sched<[WriteFCopy]> {
5095  bits<5> Rd;
5096  bits<5> Rn;
5097  let Inst{30-23} = 0b00111101;
5098  let Inst{21}    = 1;
5099  let Inst{20-19} = rmode;
5100  let Inst{18-16} = opcode;
5101  let Inst{15-10} = 0b000000;
5102  let Inst{9-5}   = Rn;
5103  let Inst{4-0}   = Rd;
5104
5105  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5106}
5107
5108
5109multiclass UnscaledConversion<string asm> {
5110  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
5111    let Inst{31} = 0; // 32-bit GPR flag
5112    let Inst{23-22} = 0b11; // 16-bit FPR flag
5113    let Predicates = [HasFullFP16];
5114  }
5115
5116  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
5117    let Inst{31} = 1; // 64-bit GPR flag
5118    let Inst{23-22} = 0b11; // 16-bit FPR flag
5119    let Predicates = [HasFullFP16];
5120  }
5121
5122  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
5123    let Inst{31} = 0; // 32-bit GPR flag
5124    let Inst{23-22} = 0b00; // 32-bit FPR flag
5125  }
5126
5127  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
5128    let Inst{31} = 1; // 64-bit GPR flag
5129    let Inst{23-22} = 0b01; // 64-bit FPR flag
5130  }
5131
5132  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
5133    let Inst{31} = 0; // 32-bit GPR flag
5134    let Inst{23-22} = 0b11; // 16-bit FPR flag
5135    let Predicates = [HasFullFP16];
5136  }
5137
5138  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
5139    let Inst{31} = 1; // 64-bit GPR flag
5140    let Inst{23-22} = 0b11; // 16-bit FPR flag
5141    let Predicates = [HasFullFP16];
5142  }
5143
5144  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
5145    let Inst{31} = 0; // 32-bit GPR flag
5146    let Inst{23-22} = 0b00; // 32-bit FPR flag
5147  }
5148
5149  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
5150    let Inst{31} = 1; // 64-bit GPR flag
5151    let Inst{23-22} = 0b01; // 64-bit FPR flag
5152  }
5153
5154  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
5155                                             asm, ".d"> {
5156    let Inst{31} = 1;
5157    let Inst{22} = 0;
5158  }
5159
5160  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
5161                                               asm, ".d"> {
5162    let Inst{31} = 1;
5163    let Inst{22} = 0;
5164  }
5165}
5166
5167//---
5168// Floating point conversion
5169//---
5170
5171let mayRaiseFPException = 1, Uses = [FPCR] in
5172class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
5173                       RegisterClass srcType, string asm, list<dag> pattern>
5174    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
5175      Sched<[WriteFCvt]> {
5176  bits<5> Rd;
5177  bits<5> Rn;
5178  let Inst{31-24} = 0b00011110;
5179  let Inst{23-22} = type;
5180  let Inst{21-17} = 0b10001;
5181  let Inst{16-15} = opcode;
5182  let Inst{14-10} = 0b10000;
5183  let Inst{9-5}   = Rn;
5184  let Inst{4-0}   = Rd;
5185}
5186
5187multiclass FPConversion<string asm> {
5188  // Double-precision to Half-precision
5189  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
5190                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
5191
5192  // Double-precision to Single-precision
5193  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
5194                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5195
5196  // Half-precision to Double-precision
5197  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5198                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5199
5200  // Half-precision to Single-precision
5201  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5202                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5203
5204  // Single-precision to Double-precision
5205  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5206                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5207
5208  // Single-precision to Half-precision
5209  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5210                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5211}
5212
5213//---
5214// Single operand floating point data processing
5215//---
5216
5217let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5218class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5219                              ValueType vt, string asm, SDPatternOperator node>
5220    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5221         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5222      Sched<[WriteF]> {
5223  bits<5> Rd;
5224  bits<5> Rn;
5225  let Inst{31-24} = 0b00011110;
5226  let Inst{21}    = 0b1;
5227  let Inst{20-15} = opcode;
5228  let Inst{14-10} = 0b10000;
5229  let Inst{9-5}   = Rn;
5230  let Inst{4-0}   = Rd;
5231}
5232
5233multiclass SingleOperandFPData<bits<4> opcode, string asm,
5234                               SDPatternOperator node = null_frag,
5235                               int fpexceptions = 1> {
5236  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
5237  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5238    let Inst{23-22} = 0b11; // 16-bit size flag
5239    let Predicates = [HasFullFP16];
5240  }
5241
5242  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5243    let Inst{23-22} = 0b00; // 32-bit size flag
5244  }
5245
5246  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5247    let Inst{23-22} = 0b01; // 64-bit size flag
5248  }
5249  }
5250}
5251
5252multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5253                                       SDPatternOperator node = null_frag>
5254    : SingleOperandFPData<opcode, asm, node, 0>;
5255
5256let mayRaiseFPException = 1, Uses = [FPCR] in
5257multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5258                  SDPatternOperator node = null_frag>{
5259
5260  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5261    let Inst{23-22} = 0b00; // 32-bit registers
5262  }
5263
5264  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5265    let Inst{23-22} = 0b01; // 64-bit registers
5266  }
5267}
5268
5269// FRInt[32|64][Z|N] instructions
5270multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5271      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5272
5273//---
5274// Two operand floating point data processing
5275//---
5276
5277let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5278class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5279                           string asm, list<dag> pat>
5280    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5281         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5282      Sched<[WriteF]> {
5283  bits<5> Rd;
5284  bits<5> Rn;
5285  bits<5> Rm;
5286  let Inst{31-24} = 0b00011110;
5287  let Inst{21}    = 1;
5288  let Inst{20-16} = Rm;
5289  let Inst{15-12} = opcode;
5290  let Inst{11-10} = 0b10;
5291  let Inst{9-5}   = Rn;
5292  let Inst{4-0}   = Rd;
5293}
5294
5295multiclass TwoOperandFPData<bits<4> opcode, string asm,
5296                            SDPatternOperator node = null_frag> {
5297  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5298                         [(set (f16 FPR16:$Rd),
5299                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5300    let Inst{23-22} = 0b11; // 16-bit size flag
5301    let Predicates = [HasFullFP16];
5302  }
5303
5304  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5305                         [(set (f32 FPR32:$Rd),
5306                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5307    let Inst{23-22} = 0b00; // 32-bit size flag
5308  }
5309
5310  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5311                         [(set (f64 FPR64:$Rd),
5312                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5313    let Inst{23-22} = 0b01; // 64-bit size flag
5314  }
5315}
5316
5317multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5318                               SDPatternOperator node> {
5319  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5320                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5321    let Inst{23-22} = 0b11; // 16-bit size flag
5322    let Predicates = [HasFullFP16];
5323  }
5324
5325  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5326                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5327    let Inst{23-22} = 0b00; // 32-bit size flag
5328  }
5329
5330  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5331                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5332    let Inst{23-22} = 0b01; // 64-bit size flag
5333  }
5334}
5335
5336
5337//---
5338// Three operand floating point data processing
5339//---
5340
5341let mayRaiseFPException = 1, Uses = [FPCR] in
5342class BaseThreeOperandFPData<bit isNegated, bit isSub,
5343                             RegisterClass regtype, string asm, list<dag> pat>
5344    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5345         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5346      Sched<[WriteFMul]> {
5347  bits<5> Rd;
5348  bits<5> Rn;
5349  bits<5> Rm;
5350  bits<5> Ra;
5351  let Inst{31-24} = 0b00011111;
5352  let Inst{21}    = isNegated;
5353  let Inst{20-16} = Rm;
5354  let Inst{15}    = isSub;
5355  let Inst{14-10} = Ra;
5356  let Inst{9-5}   = Rn;
5357  let Inst{4-0}   = Rd;
5358}
5359
5360multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5361                              SDPatternOperator node> {
5362  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5363            [(set (f16 FPR16:$Rd),
5364                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5365    let Inst{23-22} = 0b11; // 16-bit size flag
5366    let Predicates = [HasFullFP16];
5367  }
5368
5369  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5370            [(set FPR32:$Rd,
5371                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5372    let Inst{23-22} = 0b00; // 32-bit size flag
5373  }
5374
5375  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5376            [(set FPR64:$Rd,
5377                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5378    let Inst{23-22} = 0b01; // 64-bit size flag
5379  }
5380}
5381
5382//---
5383// Floating point data comparisons
5384//---
5385
5386let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5387class BaseOneOperandFPComparison<bit signalAllNans,
5388                                 RegisterClass regtype, string asm,
5389                                 list<dag> pat>
5390    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5391      Sched<[WriteFCmp]> {
5392  bits<5> Rn;
5393  let Inst{31-24} = 0b00011110;
5394  let Inst{21}    = 1;
5395
5396  let Inst{15-10} = 0b001000;
5397  let Inst{9-5}   = Rn;
5398  let Inst{4}     = signalAllNans;
5399  let Inst{3-0}   = 0b1000;
5400
5401  // Rm should be 0b00000 canonically, but we need to accept any value.
5402  let PostEncoderMethod = "fixOneOperandFPComparison";
5403}
5404
5405let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5406class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5407                                string asm, list<dag> pat>
5408    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5409      Sched<[WriteFCmp]> {
5410  bits<5> Rm;
5411  bits<5> Rn;
5412  let Inst{31-24} = 0b00011110;
5413  let Inst{21}    = 1;
5414  let Inst{20-16} = Rm;
5415  let Inst{15-10} = 0b001000;
5416  let Inst{9-5}   = Rn;
5417  let Inst{4}     = signalAllNans;
5418  let Inst{3-0}   = 0b0000;
5419}
5420
5421multiclass FPComparison<bit signalAllNans, string asm,
5422                        SDPatternOperator OpNode = null_frag> {
5423  let Defs = [NZCV] in {
5424  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5425      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5426    let Inst{23-22} = 0b11;
5427    let Predicates = [HasFullFP16];
5428  }
5429
5430  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5431      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5432    let Inst{23-22} = 0b11;
5433    let Predicates = [HasFullFP16];
5434  }
5435
5436  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5437      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5438    let Inst{23-22} = 0b00;
5439  }
5440
5441  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5442      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5443    let Inst{23-22} = 0b00;
5444  }
5445
5446  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5447      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5448    let Inst{23-22} = 0b01;
5449  }
5450
5451  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5452      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5453    let Inst{23-22} = 0b01;
5454  }
5455  } // Defs = [NZCV]
5456}
5457
5458//---
5459// Floating point conditional comparisons
5460//---
5461
5462let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5463class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5464                           string mnemonic, list<dag> pat>
5465    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5466         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5467      Sched<[WriteFCmp]> {
5468  let Uses = [NZCV];
5469  let Defs = [NZCV];
5470
5471  bits<5> Rn;
5472  bits<5> Rm;
5473  bits<4> nzcv;
5474  bits<4> cond;
5475
5476  let Inst{31-24} = 0b00011110;
5477  let Inst{21}    = 1;
5478  let Inst{20-16} = Rm;
5479  let Inst{15-12} = cond;
5480  let Inst{11-10} = 0b01;
5481  let Inst{9-5}   = Rn;
5482  let Inst{4}     = signalAllNans;
5483  let Inst{3-0}   = nzcv;
5484}
5485
5486multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5487                            SDPatternOperator OpNode = null_frag> {
5488  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5489      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5490                          (i32 imm:$cond), NZCV))]> {
5491    let Inst{23-22} = 0b11;
5492    let Predicates = [HasFullFP16];
5493  }
5494
5495  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5496      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5497                          (i32 imm:$cond), NZCV))]> {
5498    let Inst{23-22} = 0b00;
5499  }
5500
5501  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5502      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5503                          (i32 imm:$cond), NZCV))]> {
5504    let Inst{23-22} = 0b01;
5505  }
5506}
5507
5508//---
5509// Floating point conditional select
5510//---
5511
5512class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5513    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5514         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5515         [(set regtype:$Rd,
5516               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5517                          (i32 imm:$cond), NZCV))]>,
5518      Sched<[WriteF]> {
5519  bits<5> Rd;
5520  bits<5> Rn;
5521  bits<5> Rm;
5522  bits<4> cond;
5523
5524  let Inst{31-24} = 0b00011110;
5525  let Inst{21}    = 1;
5526  let Inst{20-16} = Rm;
5527  let Inst{15-12} = cond;
5528  let Inst{11-10} = 0b11;
5529  let Inst{9-5}   = Rn;
5530  let Inst{4-0}   = Rd;
5531}
5532
5533multiclass FPCondSelect<string asm> {
5534  let Uses = [NZCV] in {
5535  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5536    let Inst{23-22} = 0b11;
5537    let Predicates = [HasFullFP16];
5538  }
5539
5540  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5541    let Inst{23-22} = 0b00;
5542  }
5543
5544  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5545    let Inst{23-22} = 0b01;
5546  }
5547  } // Uses = [NZCV]
5548}
5549
5550//---
5551// Floating move immediate
5552//---
5553
5554class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5555  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5556      [(set regtype:$Rd, fpimmtype:$imm)]>,
5557    Sched<[WriteFImm]> {
5558  bits<5> Rd;
5559  bits<8> imm;
5560  let Inst{31-24} = 0b00011110;
5561  let Inst{21}    = 1;
5562  let Inst{20-13} = imm;
5563  let Inst{12-5}  = 0b10000000;
5564  let Inst{4-0}   = Rd;
5565}
5566
5567multiclass FPMoveImmediate<string asm> {
5568  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5569    let Inst{23-22} = 0b11;
5570    let Predicates = [HasFullFP16];
5571  }
5572
5573  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5574    let Inst{23-22} = 0b00;
5575  }
5576
5577  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5578    let Inst{23-22} = 0b01;
5579  }
5580}
5581} // end of 'let Predicates = [HasFPARMv8]'
5582
5583//----------------------------------------------------------------------------
5584// AdvSIMD
5585//----------------------------------------------------------------------------
5586
5587let Predicates = [HasNEON] in {
5588
5589//----------------------------------------------------------------------------
5590// AdvSIMD three register vector instructions
5591//----------------------------------------------------------------------------
5592
5593let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5594class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5595                        RegisterOperand regtype, string asm, string kind,
5596                        list<dag> pattern>
5597  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5598      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5599      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5600    Sched<[!if(Q, WriteVq, WriteVd)]> {
5601  bits<5> Rd;
5602  bits<5> Rn;
5603  bits<5> Rm;
5604  let Inst{31}    = 0;
5605  let Inst{30}    = Q;
5606  let Inst{29}    = U;
5607  let Inst{28-24} = 0b01110;
5608  let Inst{23-21} = size;
5609  let Inst{20-16} = Rm;
5610  let Inst{15-11} = opcode;
5611  let Inst{10}    = 1;
5612  let Inst{9-5}   = Rn;
5613  let Inst{4-0}   = Rd;
5614}
5615
5616let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5617class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5618                        RegisterOperand regtype, string asm, string kind,
5619                        list<dag> pattern>
5620  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5621      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5622      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5623    Sched<[!if(Q, WriteVq, WriteVd)]> {
5624  bits<5> Rd;
5625  bits<5> Rn;
5626  bits<5> Rm;
5627  let Inst{31}    = 0;
5628  let Inst{30}    = Q;
5629  let Inst{29}    = U;
5630  let Inst{28-24} = 0b01110;
5631  let Inst{23-21} = size;
5632  let Inst{20-16} = Rm;
5633  let Inst{15-11} = opcode;
5634  let Inst{10}    = 1;
5635  let Inst{9-5}   = Rn;
5636  let Inst{4-0}   = Rd;
5637}
5638
5639let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5640class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5641  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5642    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5643
5644multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5645  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5646             [(set (v8i8 V64:$dst),
5647                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5648  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5649             [(set (v16i8 V128:$dst),
5650                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5651                           (v16i8 V128:$Rm)))]>;
5652
5653  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5654                           (v4i16 V64:$RHS))),
5655          (!cast<Instruction>(NAME#"v8i8")
5656            V64:$LHS, V64:$MHS, V64:$RHS)>;
5657  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5658                           (v2i32 V64:$RHS))),
5659          (!cast<Instruction>(NAME#"v8i8")
5660            V64:$LHS, V64:$MHS, V64:$RHS)>;
5661  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5662                           (v1i64 V64:$RHS))),
5663          (!cast<Instruction>(NAME#"v8i8")
5664            V64:$LHS, V64:$MHS, V64:$RHS)>;
5665
5666  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5667                           (v8i16 V128:$RHS))),
5668      (!cast<Instruction>(NAME#"v16i8")
5669        V128:$LHS, V128:$MHS, V128:$RHS)>;
5670  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5671                           (v4i32 V128:$RHS))),
5672      (!cast<Instruction>(NAME#"v16i8")
5673        V128:$LHS, V128:$MHS, V128:$RHS)>;
5674  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5675                           (v2i64 V128:$RHS))),
5676      (!cast<Instruction>(NAME#"v16i8")
5677        V128:$LHS, V128:$MHS, V128:$RHS)>;
5678}
5679
5680// All operand sizes distinguished in the encoding.
5681multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5682                               SDPatternOperator OpNode> {
5683  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5684                                      asm, ".8b",
5685         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5686  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5687                                      asm, ".16b",
5688         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5689  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5690                                      asm, ".4h",
5691         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5692  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5693                                      asm, ".8h",
5694         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5695  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5696                                      asm, ".2s",
5697         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5698  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5699                                      asm, ".4s",
5700         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5701  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5702                                      asm, ".2d",
5703         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5704}
5705
5706multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5707  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5708          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5709  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5710          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5711  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5712          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5713
5714  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5715          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5716  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5717          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5718  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5719          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5720  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5721          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5722}
5723
5724// As above, but D sized elements unsupported.
5725multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5726                                  SDPatternOperator OpNode> {
5727  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5728                                      asm, ".8b",
5729        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5730  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5731                                      asm, ".16b",
5732        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5733  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5734                                      asm, ".4h",
5735        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5736  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5737                                      asm, ".8h",
5738        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5739  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5740                                      asm, ".2s",
5741        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5742  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5743                                      asm, ".4s",
5744        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5745}
5746
5747multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5748                                  SDPatternOperator OpNode> {
5749  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5750                                      asm, ".8b",
5751      [(set (v8i8 V64:$dst),
5752            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5753  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5754                                      asm, ".16b",
5755      [(set (v16i8 V128:$dst),
5756            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5757  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5758                                      asm, ".4h",
5759      [(set (v4i16 V64:$dst),
5760            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5761  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5762                                      asm, ".8h",
5763      [(set (v8i16 V128:$dst),
5764            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5765  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5766                                      asm, ".2s",
5767      [(set (v2i32 V64:$dst),
5768            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5769  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5770                                      asm, ".4s",
5771      [(set (v4i32 V128:$dst),
5772            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5773}
5774
5775// As above, but only B sized elements supported.
5776multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5777                                SDPatternOperator OpNode> {
5778  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5779                                      asm, ".8b",
5780    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5781  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5782                                      asm, ".16b",
5783    [(set (v16i8 V128:$Rd),
5784          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5785}
5786
5787// As above, but only floating point elements supported.
5788let mayRaiseFPException = 1, Uses = [FPCR] in
5789multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5790                                 string asm, SDPatternOperator OpNode> {
5791  let Predicates = [HasNEON, HasFullFP16] in {
5792  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5793                                      asm, ".4h",
5794        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5795  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5796                                      asm, ".8h",
5797        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5798  } // Predicates = [HasNEON, HasFullFP16]
5799  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5800                                      asm, ".2s",
5801        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5802  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5803                                      asm, ".4s",
5804        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5805  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5806                                      asm, ".2d",
5807        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5808}
5809
5810let mayRaiseFPException = 1, Uses = [FPCR] in
5811multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5812                                    string asm,
5813                                    SDPatternOperator OpNode> {
5814  let Predicates = [HasNEON, HasFullFP16] in {
5815  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5816                                      asm, ".4h",
5817        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5818  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5819                                      asm, ".8h",
5820        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5821  } // Predicates = [HasNEON, HasFullFP16]
5822  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5823                                      asm, ".2s",
5824        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5825  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5826                                      asm, ".4s",
5827        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5828  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5829                                      asm, ".2d",
5830        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5831}
5832
5833let mayRaiseFPException = 1, Uses = [FPCR] in
5834multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5835                                 string asm, SDPatternOperator OpNode> {
5836  let Predicates = [HasNEON, HasFullFP16] in {
5837  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5838                                      asm, ".4h",
5839     [(set (v4f16 V64:$dst),
5840           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5841  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5842                                      asm, ".8h",
5843     [(set (v8f16 V128:$dst),
5844           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5845  } // Predicates = [HasNEON, HasFullFP16]
5846  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5847                                      asm, ".2s",
5848     [(set (v2f32 V64:$dst),
5849           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5850  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5851                                      asm, ".4s",
5852     [(set (v4f32 V128:$dst),
5853           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5854  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5855                                      asm, ".2d",
5856     [(set (v2f64 V128:$dst),
5857           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5858}
5859
5860// As above, but D and B sized elements unsupported.
5861let mayRaiseFPException = 1, Uses = [FPCR] in
5862multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5863                                SDPatternOperator OpNode> {
5864  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5865                                      asm, ".4h",
5866        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5867  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5868                                      asm, ".8h",
5869        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5870  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5871                                      asm, ".2s",
5872        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5873  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5874                                      asm, ".4s",
5875        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5876}
5877
5878// Logical three vector ops share opcode bits, and only use B sized elements.
5879multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5880                                  SDPatternOperator OpNode = null_frag> {
5881  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5882                                     asm, ".8b",
5883                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5884  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5885                                     asm, ".16b",
5886                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5887
5888  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5889          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5890  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5891          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5892  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5893          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5894
5895  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5896      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5897  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5898      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5899  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5900      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5901}
5902
5903multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5904                                  string asm, SDPatternOperator OpNode = null_frag> {
5905  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5906                                     asm, ".8b",
5907             [(set (v8i8 V64:$dst),
5908                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5909  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5910                                     asm, ".16b",
5911             [(set (v16i8 V128:$dst),
5912                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5913                           (v16i8 V128:$Rm)))]>;
5914
5915  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5916                           (v4i16 V64:$RHS))),
5917          (!cast<Instruction>(NAME#"v8i8")
5918            V64:$LHS, V64:$MHS, V64:$RHS)>;
5919  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5920                           (v2i32 V64:$RHS))),
5921          (!cast<Instruction>(NAME#"v8i8")
5922            V64:$LHS, V64:$MHS, V64:$RHS)>;
5923  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5924                           (v1i64 V64:$RHS))),
5925          (!cast<Instruction>(NAME#"v8i8")
5926            V64:$LHS, V64:$MHS, V64:$RHS)>;
5927
5928  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5929                           (v8i16 V128:$RHS))),
5930      (!cast<Instruction>(NAME#"v16i8")
5931        V128:$LHS, V128:$MHS, V128:$RHS)>;
5932  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5933                           (v4i32 V128:$RHS))),
5934      (!cast<Instruction>(NAME#"v16i8")
5935        V128:$LHS, V128:$MHS, V128:$RHS)>;
5936  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5937                           (v2i64 V128:$RHS))),
5938      (!cast<Instruction>(NAME#"v16i8")
5939        V128:$LHS, V128:$MHS, V128:$RHS)>;
5940}
5941
5942// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5943// bytes from S-sized elements.
5944class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5945                                 string kind2, RegisterOperand RegType,
5946                                 ValueType AccumType, ValueType InputType,
5947                                 SDPatternOperator OpNode> :
5948        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5949        [(set (AccumType RegType:$dst),
5950              (OpNode (AccumType RegType:$Rd),
5951                      (InputType RegType:$Rn),
5952                      (InputType RegType:$Rm)))]> {
5953  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5954}
5955
5956multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5957  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5958                                         v2i32, v8i8, OpNode>;
5959  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5960                                         v4i32, v16i8, OpNode>;
5961}
5962
5963// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5964// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5965// 8H to 4S, when Q=1).
5966let mayRaiseFPException = 1, Uses = [FPCR] in
5967class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5968                                 string kind2, RegisterOperand RegType,
5969                                 ValueType AccumType, ValueType InputType,
5970                                 SDPatternOperator OpNode> :
5971        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5972		[(set (AccumType RegType:$dst),
5973              (OpNode (AccumType RegType:$Rd),
5974                      (InputType RegType:$Rn),
5975                      (InputType RegType:$Rm)))]> {
5976  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5977  let Inst{13} = b13;
5978}
5979
5980multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5981                                  SDPatternOperator OpNode> {
5982  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5983                                         v2f32, v4f16, OpNode>;
5984  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5985                                         v4f32, v8f16, OpNode>;
5986}
5987
5988
5989//----------------------------------------------------------------------------
5990// AdvSIMD two register vector instructions.
5991//----------------------------------------------------------------------------
5992
5993let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5994class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5995                            bits<2> size2, RegisterOperand regtype, string asm,
5996                            string dstkind, string srckind, list<dag> pattern>
5997  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5998      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5999      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
6000    Sched<[!if(Q, WriteVq, WriteVd)]> {
6001  bits<5> Rd;
6002  bits<5> Rn;
6003  let Inst{31}    = 0;
6004  let Inst{30}    = Q;
6005  let Inst{29}    = U;
6006  let Inst{28-24} = 0b01110;
6007  let Inst{23-22} = size;
6008  let Inst{21} = 0b1;
6009  let Inst{20-19} = size2;
6010  let Inst{18-17} = 0b00;
6011  let Inst{16-12} = opcode;
6012  let Inst{11-10} = 0b10;
6013  let Inst{9-5}   = Rn;
6014  let Inst{4-0}   = Rd;
6015}
6016
6017let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6018class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6019                                bits<2> size2, RegisterOperand regtype,
6020                                string asm, string dstkind, string srckind,
6021                                list<dag> pattern>
6022  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
6023      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6024      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6025    Sched<[!if(Q, WriteVq, WriteVd)]> {
6026  bits<5> Rd;
6027  bits<5> Rn;
6028  let Inst{31}    = 0;
6029  let Inst{30}    = Q;
6030  let Inst{29}    = U;
6031  let Inst{28-24} = 0b01110;
6032  let Inst{23-22} = size;
6033  let Inst{21} = 0b1;
6034  let Inst{20-19} = size2;
6035  let Inst{18-17} = 0b00;
6036  let Inst{16-12} = opcode;
6037  let Inst{11-10} = 0b10;
6038  let Inst{9-5}   = Rn;
6039  let Inst{4-0}   = Rd;
6040}
6041
6042// Supports B, H, and S element sizes.
6043multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
6044                            SDPatternOperator OpNode> {
6045  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6046                                      asm, ".8b", ".8b",
6047                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6048  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6049                                      asm, ".16b", ".16b",
6050                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6051  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6052                                      asm, ".4h", ".4h",
6053                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6054  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6055                                      asm, ".8h", ".8h",
6056                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6057  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6058                                      asm, ".2s", ".2s",
6059                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6060  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6061                                      asm, ".4s", ".4s",
6062                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6063}
6064
6065class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
6066                            RegisterOperand regtype, string asm, string dstkind,
6067                            string srckind, string amount>
6068  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
6069      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
6070      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
6071    Sched<[WriteVq]> {
6072  bits<5> Rd;
6073  bits<5> Rn;
6074  let Inst{31}    = 0;
6075  let Inst{30}    = Q;
6076  let Inst{29-24} = 0b101110;
6077  let Inst{23-22} = size;
6078  let Inst{21-10} = 0b100001001110;
6079  let Inst{9-5}   = Rn;
6080  let Inst{4-0}   = Rd;
6081}
6082
6083multiclass SIMDVectorLShiftLongBySizeBHS {
6084  let hasSideEffects = 0 in {
6085  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
6086                                             "shll", ".8h",  ".8b", "8">;
6087  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
6088                                             "shll2", ".8h", ".16b", "8">;
6089  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
6090                                             "shll", ".4s",  ".4h", "16">;
6091  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
6092                                             "shll2", ".4s", ".8h", "16">;
6093  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
6094                                             "shll", ".2d",  ".2s", "32">;
6095  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
6096                                             "shll2", ".2d", ".4s", "32">;
6097  }
6098}
6099
6100// Supports all element sizes.
6101multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
6102                             SDPatternOperator OpNode> {
6103  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6104                                      asm, ".4h", ".8b",
6105               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6106  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6107                                      asm, ".8h", ".16b",
6108               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6109  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6110                                      asm, ".2s", ".4h",
6111               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6112  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6113                                      asm, ".4s", ".8h",
6114               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6115  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6116                                      asm, ".1d", ".2s",
6117               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6118  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6119                                      asm, ".2d", ".4s",
6120               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6121}
6122
6123multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
6124                                 SDPatternOperator OpNode> {
6125  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6126                                          asm, ".4h", ".8b",
6127      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
6128                                      (v8i8 V64:$Rn)))]>;
6129  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6130                                          asm, ".8h", ".16b",
6131      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
6132                                      (v16i8 V128:$Rn)))]>;
6133  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6134                                          asm, ".2s", ".4h",
6135      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
6136                                      (v4i16 V64:$Rn)))]>;
6137  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6138                                          asm, ".4s", ".8h",
6139      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
6140                                      (v8i16 V128:$Rn)))]>;
6141  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6142                                          asm, ".1d", ".2s",
6143      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
6144                                      (v2i32 V64:$Rn)))]>;
6145  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6146                                          asm, ".2d", ".4s",
6147      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
6148                                      (v4i32 V128:$Rn)))]>;
6149}
6150
6151// Supports all element sizes, except 1xD.
6152multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
6153                                  SDPatternOperator OpNode> {
6154  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6155                                    asm, ".8b", ".8b",
6156    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
6157  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6158                                    asm, ".16b", ".16b",
6159    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
6160  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6161                                    asm, ".4h", ".4h",
6162    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
6163  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6164                                    asm, ".8h", ".8h",
6165    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
6166  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6167                                    asm, ".2s", ".2s",
6168    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
6169  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6170                                    asm, ".4s", ".4s",
6171    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
6172  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
6173                                    asm, ".2d", ".2d",
6174    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
6175}
6176
6177multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
6178                             SDPatternOperator OpNode = null_frag> {
6179  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6180                                asm, ".8b", ".8b",
6181    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6182  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6183                                asm, ".16b", ".16b",
6184    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6185  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6186                                asm, ".4h", ".4h",
6187    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6188  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6189                                asm, ".8h", ".8h",
6190    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6191  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6192                                asm, ".2s", ".2s",
6193    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6194  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6195                                asm, ".4s", ".4s",
6196    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6197  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6198                                asm, ".2d", ".2d",
6199    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6200}
6201
6202
6203// Supports only B element sizes.
6204multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6205                          SDPatternOperator OpNode> {
6206  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6207                                asm, ".8b", ".8b",
6208                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6209  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6210                                asm, ".16b", ".16b",
6211                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6212
6213}
6214
6215// Supports only B and H element sizes.
6216multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6217                                SDPatternOperator OpNode> {
6218  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6219                                asm, ".8b", ".8b",
6220                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6221  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6222                                asm, ".16b", ".16b",
6223                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6224  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6225                                asm, ".4h", ".4h",
6226                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6227  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6228                                asm, ".8h", ".8h",
6229                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6230}
6231
6232// Supports H, S and D element sizes, uses high bit of the size field
6233// as an extra opcode bit.
6234multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6235                           SDPatternOperator OpNode,
6236                           int fpexceptions = 1> {
6237  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
6238  let Predicates = [HasNEON, HasFullFP16] in {
6239  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6240                                asm, ".4h", ".4h",
6241                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6242  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6243                                asm, ".8h", ".8h",
6244                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6245  } // Predicates = [HasNEON, HasFullFP16]
6246  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6247                                asm, ".2s", ".2s",
6248                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6249  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6250                                asm, ".4s", ".4s",
6251                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6252  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6253                                asm, ".2d", ".2d",
6254                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6255  }
6256}
6257
6258multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6259                                      SDPatternOperator OpNode>
6260    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6261
6262// Supports only S and D element sizes
6263let mayRaiseFPException = 1, Uses = [FPCR] in
6264multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6265                           SDPatternOperator OpNode = null_frag> {
6266
6267  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6268                                asm, ".2s", ".2s",
6269                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6270  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6271                                asm, ".4s", ".4s",
6272                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6273  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6274                                asm, ".2d", ".2d",
6275                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6276}
6277
6278multiclass FRIntNNTVector<bit U, bit op, string asm,
6279                          SDPatternOperator OpNode = null_frag> :
6280           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6281
6282// Supports only S element size.
6283multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6284                           SDPatternOperator OpNode> {
6285  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6286                                asm, ".2s", ".2s",
6287                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6288  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6289                                asm, ".4s", ".4s",
6290                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6291}
6292
6293let mayRaiseFPException = 1, Uses = [FPCR] in
6294multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6295                           SDPatternOperator OpNode> {
6296  let Predicates = [HasNEON, HasFullFP16] in {
6297  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6298                                asm, ".4h", ".4h",
6299                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6300  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6301                                asm, ".8h", ".8h",
6302                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6303  } // Predicates = [HasNEON, HasFullFP16]
6304  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6305                                asm, ".2s", ".2s",
6306                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6307  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6308                                asm, ".4s", ".4s",
6309                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6310  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6311                                asm, ".2d", ".2d",
6312                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6313}
6314
6315let mayRaiseFPException = 1, Uses = [FPCR] in
6316multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6317                           SDPatternOperator OpNode> {
6318  let Predicates = [HasNEON, HasFullFP16] in {
6319  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6320                                asm, ".4h", ".4h",
6321                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6322  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6323                                asm, ".8h", ".8h",
6324                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6325  } // Predicates = [HasNEON, HasFullFP16]
6326  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6327                                asm, ".2s", ".2s",
6328                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6329  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6330                                asm, ".4s", ".4s",
6331                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6332  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6333                                asm, ".2d", ".2d",
6334                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6335}
6336
6337let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6338class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6339                           RegisterOperand inreg, RegisterOperand outreg,
6340                           string asm, string outkind, string inkind,
6341                           list<dag> pattern>
6342  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6343      "{\t$Rd" # outkind # ", $Rn" # inkind #
6344      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6345    Sched<[WriteVq]> {
6346  bits<5> Rd;
6347  bits<5> Rn;
6348  let Inst{31}    = 0;
6349  let Inst{30}    = Q;
6350  let Inst{29}    = U;
6351  let Inst{28-24} = 0b01110;
6352  let Inst{23-22} = size;
6353  let Inst{21-17} = 0b10000;
6354  let Inst{16-12} = opcode;
6355  let Inst{11-10} = 0b10;
6356  let Inst{9-5}   = Rn;
6357  let Inst{4-0}   = Rd;
6358}
6359
6360let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6361class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6362                           RegisterOperand inreg, RegisterOperand outreg,
6363                           string asm, string outkind, string inkind,
6364                           list<dag> pattern>
6365  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6366      "{\t$Rd" # outkind # ", $Rn" # inkind #
6367      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6368    Sched<[WriteVq]> {
6369  bits<5> Rd;
6370  bits<5> Rn;
6371  let Inst{31}    = 0;
6372  let Inst{30}    = Q;
6373  let Inst{29}    = U;
6374  let Inst{28-24} = 0b01110;
6375  let Inst{23-22} = size;
6376  let Inst{21-17} = 0b10000;
6377  let Inst{16-12} = opcode;
6378  let Inst{11-10} = 0b10;
6379  let Inst{9-5}   = Rn;
6380  let Inst{4-0}   = Rd;
6381}
6382
6383multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6384                              SDPatternOperator OpNode> {
6385  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6386                                      asm, ".8b", ".8h",
6387        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6388  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6389                                      asm#"2", ".16b", ".8h", []>;
6390  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6391                                      asm, ".4h", ".4s",
6392        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6393  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6394                                      asm#"2", ".8h", ".4s", []>;
6395  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6396                                      asm, ".2s", ".2d",
6397        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6398  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6399                                      asm#"2", ".4s", ".2d", []>;
6400
6401  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6402            (!cast<Instruction>(NAME # "v16i8")
6403                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6404  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6405            (!cast<Instruction>(NAME # "v8i16")
6406                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6407  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6408            (!cast<Instruction>(NAME # "v4i32")
6409                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6410}
6411
6412class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6413                           bits<5> opcode, RegisterOperand regtype, string asm,
6414                           string kind, string zero, ValueType dty,
6415                           ValueType sty, SDNode OpNode>
6416  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6417      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6418      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6419      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6420    Sched<[!if(Q, WriteVq, WriteVd)]> {
6421  bits<5> Rd;
6422  bits<5> Rn;
6423  let Inst{31}    = 0;
6424  let Inst{30}    = Q;
6425  let Inst{29}    = U;
6426  let Inst{28-24} = 0b01110;
6427  let Inst{23-22} = size;
6428  let Inst{21} = 0b1;
6429  let Inst{20-19} = size2;
6430  let Inst{18-17} = 0b00;
6431  let Inst{16-12} = opcode;
6432  let Inst{11-10} = 0b10;
6433  let Inst{9-5}   = Rn;
6434  let Inst{4-0}   = Rd;
6435}
6436
6437// Comparisons support all element sizes, except 1xD.
6438multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6439                            SDNode OpNode> {
6440  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6441                                     asm, ".8b", "0",
6442                                     v8i8, v8i8, OpNode>;
6443  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6444                                     asm, ".16b", "0",
6445                                     v16i8, v16i8, OpNode>;
6446  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6447                                     asm, ".4h", "0",
6448                                     v4i16, v4i16, OpNode>;
6449  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6450                                     asm, ".8h", "0",
6451                                     v8i16, v8i16, OpNode>;
6452  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6453                                     asm, ".2s", "0",
6454                                     v2i32, v2i32, OpNode>;
6455  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6456                                     asm, ".4s", "0",
6457                                     v4i32, v4i32, OpNode>;
6458  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6459                                     asm, ".2d", "0",
6460                                     v2i64, v2i64, OpNode>;
6461}
6462
6463// FP Comparisons support only S and D element sizes (and H for v8.2a).
6464multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6465                              string asm, SDNode OpNode> {
6466
6467  let mayRaiseFPException = 1, Uses = [FPCR] in {
6468  let Predicates = [HasNEON, HasFullFP16] in {
6469  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6470                                     asm, ".4h", "0.0",
6471                                     v4i16, v4f16, OpNode>;
6472  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6473                                     asm, ".8h", "0.0",
6474                                     v8i16, v8f16, OpNode>;
6475  } // Predicates = [HasNEON, HasFullFP16]
6476  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6477                                     asm, ".2s", "0.0",
6478                                     v2i32, v2f32, OpNode>;
6479  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6480                                     asm, ".4s", "0.0",
6481                                     v4i32, v4f32, OpNode>;
6482  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6483                                     asm, ".2d", "0.0",
6484                                     v2i64, v2f64, OpNode>;
6485  }
6486
6487  let Predicates = [HasNEON, HasFullFP16] in {
6488  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6489                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6490  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6491                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6492  }
6493  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6494                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6495  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6496                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6497  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6498                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6499  let Predicates = [HasNEON, HasFullFP16] in {
6500  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6501                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6502  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6503                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6504  }
6505  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6506                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6507  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6508                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6509  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6510                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6511}
6512
6513let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6514class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6515                             RegisterOperand outtype, RegisterOperand intype,
6516                             string asm, string VdTy, string VnTy,
6517                             list<dag> pattern>
6518  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6519      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6520    Sched<[WriteVq]> {
6521  bits<5> Rd;
6522  bits<5> Rn;
6523  let Inst{31}    = 0;
6524  let Inst{30}    = Q;
6525  let Inst{29}    = U;
6526  let Inst{28-24} = 0b01110;
6527  let Inst{23-22} = size;
6528  let Inst{21-17} = 0b10000;
6529  let Inst{16-12} = opcode;
6530  let Inst{11-10} = 0b10;
6531  let Inst{9-5}   = Rn;
6532  let Inst{4-0}   = Rd;
6533}
6534
6535let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6536class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6537                             RegisterOperand outtype, RegisterOperand intype,
6538                             string asm, string VdTy, string VnTy,
6539                             list<dag> pattern>
6540  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6541      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6542    Sched<[WriteVq]> {
6543  bits<5> Rd;
6544  bits<5> Rn;
6545  let Inst{31}    = 0;
6546  let Inst{30}    = Q;
6547  let Inst{29}    = U;
6548  let Inst{28-24} = 0b01110;
6549  let Inst{23-22} = size;
6550  let Inst{21-17} = 0b10000;
6551  let Inst{16-12} = opcode;
6552  let Inst{11-10} = 0b10;
6553  let Inst{9-5}   = Rn;
6554  let Inst{4-0}   = Rd;
6555}
6556
6557multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6558  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6559                                    asm, ".4s", ".4h", []>;
6560  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6561                                    asm#"2", ".4s", ".8h", []>;
6562  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6563                                    asm, ".2d", ".2s", []>;
6564  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6565                                    asm#"2", ".2d", ".4s", []>;
6566}
6567
6568multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6569  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6570                                    asm, ".4h", ".4s", []>;
6571  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6572                                    asm#"2", ".8h", ".4s", []>;
6573  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6574                                    asm, ".2s", ".2d", []>;
6575  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6576                                    asm#"2", ".4s", ".2d", []>;
6577}
6578
6579multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6580                                     Intrinsic OpNode> {
6581  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6582                                     asm, ".2s", ".2d",
6583                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6584  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6585                                    asm#"2", ".4s", ".2d", []>;
6586
6587  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6588            (!cast<Instruction>(NAME # "v4f32")
6589                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6590}
6591
6592//----------------------------------------------------------------------------
6593// AdvSIMD three register different-size vector instructions.
6594//----------------------------------------------------------------------------
6595
6596let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6597class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6598                      RegisterOperand outtype, RegisterOperand intype1,
6599                      RegisterOperand intype2, string asm,
6600                      string outkind, string inkind1, string inkind2,
6601                      list<dag> pattern>
6602  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6603      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6604      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6605    Sched<[WriteVq]> {
6606  bits<5> Rd;
6607  bits<5> Rn;
6608  bits<5> Rm;
6609  let Inst{31}    = 0;
6610  let Inst{30}    = size{0};
6611  let Inst{29}    = U;
6612  let Inst{28-24} = 0b01110;
6613  let Inst{23-22} = size{2-1};
6614  let Inst{21}    = 1;
6615  let Inst{20-16} = Rm;
6616  let Inst{15-12} = opcode;
6617  let Inst{11-10} = 0b00;
6618  let Inst{9-5}   = Rn;
6619  let Inst{4-0}   = Rd;
6620}
6621
6622let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6623class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6624                      RegisterOperand outtype, RegisterOperand intype1,
6625                      RegisterOperand intype2, string asm,
6626                      string outkind, string inkind1, string inkind2,
6627                      list<dag> pattern>
6628  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6629      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6630      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6631    Sched<[WriteVq]> {
6632  bits<5> Rd;
6633  bits<5> Rn;
6634  bits<5> Rm;
6635  let Inst{31}    = 0;
6636  let Inst{30}    = size{0};
6637  let Inst{29}    = U;
6638  let Inst{28-24} = 0b01110;
6639  let Inst{23-22} = size{2-1};
6640  let Inst{21}    = 1;
6641  let Inst{20-16} = Rm;
6642  let Inst{15-12} = opcode;
6643  let Inst{11-10} = 0b00;
6644  let Inst{9-5}   = Rn;
6645  let Inst{4-0}   = Rd;
6646}
6647
6648// FIXME: TableGen doesn't know how to deal with expanded types that also
6649//        change the element count (in this case, placing the results in
6650//        the high elements of the result register rather than the low
6651//        elements). Until that's fixed, we can't code-gen those.
6652multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6653                                    Intrinsic IntOp> {
6654  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6655                                                  V64, V128, V128,
6656                                                  asm, ".8b", ".8h", ".8h",
6657     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6658  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6659                                                  V128, V128, V128,
6660                                                  asm#"2", ".16b", ".8h", ".8h",
6661     []>;
6662  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6663                                                  V64, V128, V128,
6664                                                  asm, ".4h", ".4s", ".4s",
6665     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6666  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6667                                                  V128, V128, V128,
6668                                                  asm#"2", ".8h", ".4s", ".4s",
6669     []>;
6670  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6671                                                  V64, V128, V128,
6672                                                  asm, ".2s", ".2d", ".2d",
6673     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6674  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6675                                                  V128, V128, V128,
6676                                                  asm#"2", ".4s", ".2d", ".2d",
6677     []>;
6678
6679
6680  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6681  // a version attached to an instruction.
6682  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6683                                                   (v8i16 V128:$Rm))),
6684            (!cast<Instruction>(NAME # "v8i16_v16i8")
6685                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6686                V128:$Rn, V128:$Rm)>;
6687  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6688                                                    (v4i32 V128:$Rm))),
6689            (!cast<Instruction>(NAME # "v4i32_v8i16")
6690                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6691                V128:$Rn, V128:$Rm)>;
6692  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6693                                                    (v2i64 V128:$Rm))),
6694            (!cast<Instruction>(NAME # "v2i64_v4i32")
6695                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6696                V128:$Rn, V128:$Rm)>;
6697}
6698
6699multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6700                                      SDPatternOperator OpNode> {
6701  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6702                                            V128, V64, V64,
6703                                            asm, ".8h", ".8b", ".8b",
6704      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6705  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6706                                            V128, V128, V128,
6707                                            asm#"2", ".8h", ".16b", ".16b", []>;
6708  let Predicates = [HasAES] in {
6709    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6710                                              V128, V64, V64,
6711                                              asm, ".1q", ".1d", ".1d",
6712        [(set (v16i8 V128:$Rd), (OpNode (v1i64 V64:$Rn), (v1i64 V64:$Rm)))]>;
6713    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6714                                              V128, V128, V128,
6715                                              asm#"2", ".1q", ".2d", ".2d",
6716        [(set (v16i8 V128:$Rd), (OpNode (extract_high_v2i64 (v2i64 V128:$Rn)),
6717                                        (extract_high_v2i64 (v2i64 V128:$Rm))))]>;
6718  }
6719
6720  def : Pat<(v8i16 (OpNode (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6721                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6722      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6723}
6724
6725multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6726                                 SDPatternOperator OpNode> {
6727  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6728                                                  V128, V64, V64,
6729                                                  asm, ".4s", ".4h", ".4h",
6730      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6731  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6732                                                  V128, V128, V128,
6733                                                  asm#"2", ".4s", ".8h", ".8h",
6734      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6735                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6736  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6737                                                  V128, V64, V64,
6738                                                  asm, ".2d", ".2s", ".2s",
6739      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6740  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6741                                                  V128, V128, V128,
6742                                                  asm#"2", ".2d", ".4s", ".4s",
6743      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6744                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6745}
6746
6747multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6748                                  SDPatternOperator OpNode = null_frag> {
6749  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6750                                                  V128, V64, V64,
6751                                                  asm, ".8h", ".8b", ".8b",
6752      [(set (v8i16 V128:$Rd),
6753            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6754  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6755                                                 V128, V128, V128,
6756                                                 asm#"2", ".8h", ".16b", ".16b",
6757      [(set (v8i16 V128:$Rd),
6758            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6759                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
6760  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6761                                                  V128, V64, V64,
6762                                                  asm, ".4s", ".4h", ".4h",
6763      [(set (v4i32 V128:$Rd),
6764            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6765  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6766                                                  V128, V128, V128,
6767                                                  asm#"2", ".4s", ".8h", ".8h",
6768      [(set (v4i32 V128:$Rd),
6769            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6770                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6771  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6772                                                  V128, V64, V64,
6773                                                  asm, ".2d", ".2s", ".2s",
6774      [(set (v2i64 V128:$Rd),
6775            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6776  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6777                                                  V128, V128, V128,
6778                                                  asm#"2", ".2d", ".4s", ".4s",
6779      [(set (v2i64 V128:$Rd),
6780            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6781                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6782}
6783
6784multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6785                                          string asm,
6786                                          SDPatternOperator OpNode> {
6787  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6788                                                  V128, V64, V64,
6789                                                  asm, ".8h", ".8b", ".8b",
6790    [(set (v8i16 V128:$dst),
6791          (add (v8i16 V128:$Rd),
6792               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6793  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6794                                                 V128, V128, V128,
6795                                                 asm#"2", ".8h", ".16b", ".16b",
6796    [(set (v8i16 V128:$dst),
6797          (add (v8i16 V128:$Rd),
6798               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6799                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
6800  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6801                                                  V128, V64, V64,
6802                                                  asm, ".4s", ".4h", ".4h",
6803    [(set (v4i32 V128:$dst),
6804          (add (v4i32 V128:$Rd),
6805               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6806  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6807                                                  V128, V128, V128,
6808                                                  asm#"2", ".4s", ".8h", ".8h",
6809    [(set (v4i32 V128:$dst),
6810          (add (v4i32 V128:$Rd),
6811               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6812                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
6813  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6814                                                  V128, V64, V64,
6815                                                  asm, ".2d", ".2s", ".2s",
6816    [(set (v2i64 V128:$dst),
6817          (add (v2i64 V128:$Rd),
6818               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6819  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6820                                                  V128, V128, V128,
6821                                                  asm#"2", ".2d", ".4s", ".4s",
6822    [(set (v2i64 V128:$dst),
6823          (add (v2i64 V128:$Rd),
6824               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6825                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
6826}
6827
6828multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6829                                  SDPatternOperator OpNode = null_frag> {
6830  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6831                                                  V128, V64, V64,
6832                                                  asm, ".8h", ".8b", ".8b",
6833      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6834  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6835                                                 V128, V128, V128,
6836                                                 asm#"2", ".8h", ".16b", ".16b",
6837      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6838                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6839  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6840                                                  V128, V64, V64,
6841                                                  asm, ".4s", ".4h", ".4h",
6842      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6843  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6844                                                  V128, V128, V128,
6845                                                  asm#"2", ".4s", ".8h", ".8h",
6846      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6847                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6848  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6849                                                  V128, V64, V64,
6850                                                  asm, ".2d", ".2s", ".2s",
6851      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6852  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6853                                                  V128, V128, V128,
6854                                                  asm#"2", ".2d", ".4s", ".4s",
6855      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6856                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6857}
6858
6859multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6860                                      string asm,
6861                                      SDPatternOperator OpNode> {
6862  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6863                                                  V128, V64, V64,
6864                                                  asm, ".8h", ".8b", ".8b",
6865    [(set (v8i16 V128:$dst),
6866          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6867  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6868                                                 V128, V128, V128,
6869                                                 asm#"2", ".8h", ".16b", ".16b",
6870    [(set (v8i16 V128:$dst),
6871          (OpNode (v8i16 V128:$Rd),
6872                  (extract_high_v16i8 (v16i8 V128:$Rn)),
6873                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6874  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6875                                                  V128, V64, V64,
6876                                                  asm, ".4s", ".4h", ".4h",
6877    [(set (v4i32 V128:$dst),
6878          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6879  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6880                                                  V128, V128, V128,
6881                                                  asm#"2", ".4s", ".8h", ".8h",
6882    [(set (v4i32 V128:$dst),
6883          (OpNode (v4i32 V128:$Rd),
6884                  (extract_high_v8i16 (v8i16 V128:$Rn)),
6885                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6886  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6887                                                  V128, V64, V64,
6888                                                  asm, ".2d", ".2s", ".2s",
6889    [(set (v2i64 V128:$dst),
6890          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6891  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6892                                                  V128, V128, V128,
6893                                                  asm#"2", ".2d", ".4s", ".4s",
6894    [(set (v2i64 V128:$dst),
6895          (OpNode (v2i64 V128:$Rd),
6896                  (extract_high_v4i32 (v4i32 V128:$Rn)),
6897                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6898}
6899
6900multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6901                                           SDPatternOperator Accum> {
6902  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6903                                                  V128, V64, V64,
6904                                                  asm, ".4s", ".4h", ".4h",
6905    [(set (v4i32 V128:$dst),
6906          (Accum (v4i32 V128:$Rd),
6907                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6908                                                (v4i16 V64:$Rm)))))]>;
6909  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6910                                                  V128, V128, V128,
6911                                                  asm#"2", ".4s", ".8h", ".8h",
6912    [(set (v4i32 V128:$dst),
6913          (Accum (v4i32 V128:$Rd),
6914                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
6915                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6916  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6917                                                  V128, V64, V64,
6918                                                  asm, ".2d", ".2s", ".2s",
6919    [(set (v2i64 V128:$dst),
6920          (Accum (v2i64 V128:$Rd),
6921                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6922                                                (v2i32 V64:$Rm)))))]>;
6923  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6924                                                  V128, V128, V128,
6925                                                  asm#"2", ".2d", ".4s", ".4s",
6926    [(set (v2i64 V128:$dst),
6927          (Accum (v2i64 V128:$Rd),
6928                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
6929                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6930}
6931
6932multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6933                                  SDPatternOperator OpNode> {
6934  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6935                                                  V128, V128, V64,
6936                                                  asm, ".8h", ".8h", ".8b",
6937       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6938  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6939                                                  V128, V128, V128,
6940                                                  asm#"2", ".8h", ".8h", ".16b",
6941       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6942                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6943  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6944                                                  V128, V128, V64,
6945                                                  asm, ".4s", ".4s", ".4h",
6946       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6947  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6948                                                  V128, V128, V128,
6949                                                  asm#"2", ".4s", ".4s", ".8h",
6950       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6951                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6952  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6953                                                  V128, V128, V64,
6954                                                  asm, ".2d", ".2d", ".2s",
6955       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6956  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6957                                                  V128, V128, V128,
6958                                                  asm#"2", ".2d", ".2d", ".4s",
6959       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6960                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6961}
6962
6963//----------------------------------------------------------------------------
6964// AdvSIMD bitwise extract from vector
6965//----------------------------------------------------------------------------
6966
6967class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6968                             string asm, string kind>
6969  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6970      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6971      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6972      [(set (vty regtype:$Rd),
6973            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6974    Sched<[!if(size, WriteVq, WriteVd)]> {
6975  bits<5> Rd;
6976  bits<5> Rn;
6977  bits<5> Rm;
6978  bits<4> imm;
6979  let Inst{31}    = 0;
6980  let Inst{30}    = size;
6981  let Inst{29-21} = 0b101110000;
6982  let Inst{20-16} = Rm;
6983  let Inst{15}    = 0;
6984  let Inst{14-11} = imm;
6985  let Inst{10}    = 0;
6986  let Inst{9-5}   = Rn;
6987  let Inst{4-0}   = Rd;
6988}
6989
6990
6991multiclass SIMDBitwiseExtract<string asm> {
6992  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6993    let imm{3} = 0;
6994  }
6995  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6996}
6997
6998//----------------------------------------------------------------------------
6999// AdvSIMD zip vector
7000//----------------------------------------------------------------------------
7001
7002class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
7003                        string asm, string kind, SDNode OpNode, ValueType valty>
7004  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7005      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
7006      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
7007      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
7008    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
7009  bits<5> Rd;
7010  bits<5> Rn;
7011  bits<5> Rm;
7012  let Inst{31}    = 0;
7013  let Inst{30}    = size{0};
7014  let Inst{29-24} = 0b001110;
7015  let Inst{23-22} = size{2-1};
7016  let Inst{21}    = 0;
7017  let Inst{20-16} = Rm;
7018  let Inst{15}    = 0;
7019  let Inst{14-12} = opc;
7020  let Inst{11-10} = 0b10;
7021  let Inst{9-5}   = Rn;
7022  let Inst{4-0}   = Rd;
7023}
7024
7025multiclass SIMDZipVector<bits<3>opc, string asm,
7026                         SDNode OpNode> {
7027  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
7028      asm, ".8b", OpNode, v8i8>;
7029  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
7030      asm, ".16b", OpNode, v16i8>;
7031  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
7032      asm, ".4h", OpNode, v4i16>;
7033  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
7034      asm, ".8h", OpNode, v8i16>;
7035  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
7036      asm, ".2s", OpNode, v2i32>;
7037  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
7038      asm, ".4s", OpNode, v4i32>;
7039  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
7040      asm, ".2d", OpNode, v2i64>;
7041
7042  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
7043        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7044  def : Pat<(v4bf16 (OpNode V64:$Rn, V64:$Rm)),
7045        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7046  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
7047        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7048  def : Pat<(v8bf16 (OpNode V128:$Rn, V128:$Rm)),
7049        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7050  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
7051        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
7052  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
7053        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
7054  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
7055        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
7056}
7057
7058//----------------------------------------------------------------------------
7059// AdvSIMD three register scalar instructions
7060//----------------------------------------------------------------------------
7061
7062let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7063class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
7064                        RegisterClass regtype, string asm,
7065                        list<dag> pattern>
7066  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7067      "\t$Rd, $Rn, $Rm", "", pattern>,
7068    Sched<[WriteVd]> {
7069  bits<5> Rd;
7070  bits<5> Rn;
7071  bits<5> Rm;
7072  let Inst{31-30} = 0b01;
7073  let Inst{29}    = U;
7074  let Inst{28-24} = 0b11110;
7075  let Inst{23-21} = size;
7076  let Inst{20-16} = Rm;
7077  let Inst{15-11} = opcode;
7078  let Inst{10}    = 1;
7079  let Inst{9-5}   = Rn;
7080  let Inst{4-0}   = Rd;
7081}
7082
7083let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7084class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
7085                        dag oops, dag iops, string asm,
7086            list<dag> pattern>
7087  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
7088    Sched<[WriteVd]> {
7089  bits<5> Rd;
7090  bits<5> Rn;
7091  bits<5> Rm;
7092  let Inst{31-30} = 0b01;
7093  let Inst{29}    = U;
7094  let Inst{28-24} = 0b11110;
7095  let Inst{23-22} = size;
7096  let Inst{21}    = R;
7097  let Inst{20-16} = Rm;
7098  let Inst{15-11} = opcode;
7099  let Inst{10}    = 1;
7100  let Inst{9-5}   = Rn;
7101  let Inst{4-0}   = Rd;
7102}
7103
7104multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
7105                            SDPatternOperator OpNode> {
7106  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7107    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7108}
7109
7110multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
7111                               SDPatternOperator OpNode> {
7112  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7113    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7114  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
7115  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7116  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
7117
7118  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7119            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
7120  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
7121            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
7122}
7123
7124multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
7125                             SDPatternOperator OpNode> {
7126  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
7127                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7128  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7129}
7130
7131multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
7132  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
7133                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
7134                                     asm, []>;
7135  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
7136                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
7137                                     asm, []>;
7138}
7139
7140multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
7141                             SDPatternOperator OpNode = null_frag,
7142                             Predicate pred = HasNEON> {
7143  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7144    let Predicates = [pred] in {
7145    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7146      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7147    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7148      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7149    }
7150    let Predicates = [pred, HasFullFP16] in {
7151    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7152      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
7153    }
7154  }
7155
7156  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7157            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7158}
7159
7160multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
7161                                SDPatternOperator OpNode = null_frag> {
7162  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7163    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7164      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7165    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7166      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
7167    let Predicates = [HasNEON, HasFullFP16] in {
7168    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7169      []>;
7170    } // Predicates = [HasNEON, HasFullFP16]
7171  }
7172
7173  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7174            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7175}
7176
7177class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
7178              dag oops, dag iops, string asm, string cstr, list<dag> pat>
7179  : I<oops, iops, asm,
7180      "\t$Rd, $Rn, $Rm", cstr, pat>,
7181    Sched<[WriteVd]> {
7182  bits<5> Rd;
7183  bits<5> Rn;
7184  bits<5> Rm;
7185  let Inst{31-30} = 0b01;
7186  let Inst{29}    = U;
7187  let Inst{28-24} = 0b11110;
7188  let Inst{23-22} = size;
7189  let Inst{21}    = 1;
7190  let Inst{20-16} = Rm;
7191  let Inst{15-11} = opcode;
7192  let Inst{10}    = 0;
7193  let Inst{9-5}   = Rn;
7194  let Inst{4-0}   = Rd;
7195}
7196
7197let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7198multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
7199                                  SDPatternOperator OpNode = null_frag> {
7200  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7201                                      (outs FPR32:$Rd),
7202                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7203  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7204                                      (outs FPR64:$Rd),
7205                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7206            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7207}
7208
7209let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7210multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7211                                  SDPatternOperator OpNode = null_frag> {
7212  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7213                                      (outs FPR32:$dst),
7214                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7215                                      asm, "$Rd = $dst", []>;
7216  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7217                                      (outs FPR64:$dst),
7218                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7219                                      asm, "$Rd = $dst",
7220            [(set (i64 FPR64:$dst),
7221                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7222}
7223
7224//----------------------------------------------------------------------------
7225// AdvSIMD two register scalar instructions
7226//----------------------------------------------------------------------------
7227
7228let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7229class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7230                        RegisterClass regtype, RegisterClass regtype2,
7231                        string asm, list<dag> pat>
7232  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7233      "\t$Rd, $Rn", "", pat>,
7234    Sched<[WriteVd]> {
7235  bits<5> Rd;
7236  bits<5> Rn;
7237  let Inst{31-30} = 0b01;
7238  let Inst{29}    = U;
7239  let Inst{28-24} = 0b11110;
7240  let Inst{23-22} = size;
7241  let Inst{21} = 0b1;
7242  let Inst{20-19} = size2;
7243  let Inst{18-17} = 0b00;
7244  let Inst{16-12} = opcode;
7245  let Inst{11-10} = 0b10;
7246  let Inst{9-5}   = Rn;
7247  let Inst{4-0}   = Rd;
7248}
7249
7250let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7251class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7252                        RegisterClass regtype, RegisterClass regtype2,
7253                        string asm, list<dag> pat>
7254  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7255      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7256    Sched<[WriteVd]> {
7257  bits<5> Rd;
7258  bits<5> Rn;
7259  let Inst{31-30} = 0b01;
7260  let Inst{29}    = U;
7261  let Inst{28-24} = 0b11110;
7262  let Inst{23-22} = size;
7263  let Inst{21-17} = 0b10000;
7264  let Inst{16-12} = opcode;
7265  let Inst{11-10} = 0b10;
7266  let Inst{9-5}   = Rn;
7267  let Inst{4-0}   = Rd;
7268}
7269
7270
7271let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7272class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7273                        RegisterClass regtype, string asm, string zero>
7274  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7275      "\t$Rd, $Rn, #" # zero, "", []>,
7276    Sched<[WriteVd]> {
7277  bits<5> Rd;
7278  bits<5> Rn;
7279  let Inst{31-30} = 0b01;
7280  let Inst{29}    = U;
7281  let Inst{28-24} = 0b11110;
7282  let Inst{23-22} = size;
7283  let Inst{21} = 0b1;
7284  let Inst{20-19} = size2;
7285  let Inst{18-17} = 0b00;
7286  let Inst{16-12} = opcode;
7287  let Inst{11-10} = 0b10;
7288  let Inst{9-5}   = Rn;
7289  let Inst{4-0}   = Rd;
7290}
7291
7292let mayRaiseFPException = 1, Uses = [FPCR] in
7293class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7294  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7295     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7296    Sched<[WriteVd]> {
7297  bits<5> Rd;
7298  bits<5> Rn;
7299  let Inst{31-17} = 0b011111100110000;
7300  let Inst{16-12} = opcode;
7301  let Inst{11-10} = 0b10;
7302  let Inst{9-5}   = Rn;
7303  let Inst{4-0}   = Rd;
7304}
7305
7306multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7307                             SDPatternOperator OpNode> {
7308  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7309
7310  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7311            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7312}
7313
7314multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7315                              SDPatternOperator OpNode> {
7316  let mayRaiseFPException = 1, Uses = [FPCR] in {
7317  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7318  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7319  let Predicates = [HasNEON, HasFullFP16] in {
7320  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7321  }
7322  }
7323
7324  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7325                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7326  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7327                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7328  let Predicates = [HasNEON, HasFullFP16] in {
7329  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7330                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7331  }
7332
7333  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7334            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7335}
7336
7337multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7338                          SDPatternOperator OpNode = null_frag,
7339                          list<Predicate> preds = []> {
7340  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7341    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7342
7343  let Predicates = preds in {
7344  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7345            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7346  }
7347}
7348
7349let mayRaiseFPException = 1, Uses = [FPCR] in
7350multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7351                           Predicate pred = HasNEON> {
7352  let Predicates = [pred] in {
7353  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7354  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7355  }
7356  let Predicates = [pred, HasFullFP16] in {
7357  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7358  }
7359}
7360
7361let mayRaiseFPException = 1, Uses = [FPCR] in
7362multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7363                              SDPatternOperator OpNode> {
7364  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7365                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7366  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7367                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7368  let Predicates = [HasNEON, HasFullFP16] in {
7369  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7370                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7371  }
7372}
7373
7374multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7375                             SDPatternOperator OpNode = null_frag> {
7376  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7377    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7378           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7379    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7380           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7381    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7382    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7383  }
7384
7385  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7386            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7387}
7388
7389multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7390                                 Intrinsic OpNode> {
7391  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7392    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7393        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7394    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7395        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7396    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7397    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7398  }
7399
7400  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7401            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7402}
7403
7404
7405
7406let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7407multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7408                                 SDPatternOperator OpNode = null_frag> {
7409  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7410        [(set (f32 FPR32:$Rd), (OpNode (f64 FPR64:$Rn)))]>;
7411  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7412  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7413}
7414
7415//----------------------------------------------------------------------------
7416// AdvSIMD scalar pairwise instructions
7417//----------------------------------------------------------------------------
7418
7419let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7420class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7421                        RegisterOperand regtype, RegisterOperand vectype,
7422                        string asm, string kind>
7423  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7424      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7425    Sched<[WriteVd]> {
7426  bits<5> Rd;
7427  bits<5> Rn;
7428  let Inst{31-30} = 0b01;
7429  let Inst{29}    = U;
7430  let Inst{28-24} = 0b11110;
7431  let Inst{23-22} = size;
7432  let Inst{21-17} = 0b11000;
7433  let Inst{16-12} = opcode;
7434  let Inst{11-10} = 0b10;
7435  let Inst{9-5}   = Rn;
7436  let Inst{4-0}   = Rd;
7437}
7438
7439multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7440  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7441                                      asm, ".2d">;
7442}
7443
7444let mayRaiseFPException = 1, Uses = [FPCR] in
7445multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7446  let Predicates = [HasNEON, HasFullFP16] in {
7447  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7448                                      asm, ".2h">;
7449  }
7450  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7451                                      asm, ".2s">;
7452  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7453                                      asm, ".2d">;
7454}
7455
7456//----------------------------------------------------------------------------
7457// AdvSIMD across lanes instructions
7458//----------------------------------------------------------------------------
7459
7460let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7461class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7462                          RegisterClass regtype, RegisterOperand vectype,
7463                          string asm, string kind, list<dag> pattern>
7464  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7465      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7466    Sched<[!if(Q, WriteVq, WriteVd)]> {
7467  bits<5> Rd;
7468  bits<5> Rn;
7469  let Inst{31}    = 0;
7470  let Inst{30}    = Q;
7471  let Inst{29}    = U;
7472  let Inst{28-24} = 0b01110;
7473  let Inst{23-22} = size;
7474  let Inst{21-17} = 0b11000;
7475  let Inst{16-12} = opcode;
7476  let Inst{11-10} = 0b10;
7477  let Inst{9-5}   = Rn;
7478  let Inst{4-0}   = Rd;
7479}
7480
7481multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7482                              string asm> {
7483  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7484                                   asm, ".8b", []>;
7485  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7486                                   asm, ".16b", []>;
7487  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7488                                   asm, ".4h", []>;
7489  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7490                                   asm, ".8h", []>;
7491  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7492                                   asm, ".4s", []>;
7493}
7494
7495multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7496  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7497                                   asm, ".8b", []>;
7498  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7499                                   asm, ".16b", []>;
7500  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7501                                   asm, ".4h", []>;
7502  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7503                                   asm, ".8h", []>;
7504  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7505                                   asm, ".4s", []>;
7506}
7507
7508let mayRaiseFPException = 1, Uses = [FPCR] in
7509multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7510                            SDPatternOperator intOp> {
7511  let Predicates = [HasNEON, HasFullFP16] in {
7512  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7513                                   asm, ".4h",
7514        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7515  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7516                                   asm, ".8h",
7517        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7518  } // Predicates = [HasNEON, HasFullFP16]
7519  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7520                                   asm, ".4s",
7521        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7522}
7523
7524//----------------------------------------------------------------------------
7525// AdvSIMD INS/DUP instructions
7526//----------------------------------------------------------------------------
7527
7528// FIXME: There has got to be a better way to factor these. ugh.
7529
7530class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7531                     string operands, string constraints, list<dag> pattern>
7532  : I<outs, ins, asm, operands, constraints, pattern>,
7533    Sched<[!if(Q, WriteVq, WriteVd)]> {
7534  bits<5> Rd;
7535  bits<5> Rn;
7536  let Inst{31} = 0;
7537  let Inst{30} = Q;
7538  let Inst{29} = op;
7539  let Inst{28-21} = 0b01110000;
7540  let Inst{15} = 0;
7541  let Inst{10} = 1;
7542  let Inst{9-5} = Rn;
7543  let Inst{4-0} = Rd;
7544}
7545
7546class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7547                      RegisterOperand vecreg, RegisterClass regtype>
7548  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7549                   "{\t$Rd" # size # ", $Rn" #
7550                   "|" # size # "\t$Rd, $Rn}", "",
7551                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7552  let Inst{20-16} = imm5;
7553  let Inst{14-11} = 0b0001;
7554}
7555
7556class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7557                         ValueType vectype, ValueType insreg,
7558                         RegisterOperand vecreg, Operand idxtype,
7559                         SDNode OpNode>
7560  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7561                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7562                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7563                 [(set (vectype vecreg:$Rd),
7564                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7565  let Inst{14-11} = 0b0000;
7566}
7567
7568class SIMDDup64FromElement
7569  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7570                       VectorIndexD, AArch64duplane64> {
7571  bits<1> idx;
7572  let Inst{20} = idx;
7573  let Inst{19-16} = 0b1000;
7574}
7575
7576class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7577                           RegisterOperand vecreg>
7578  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7579                       VectorIndexS, AArch64duplane32> {
7580  bits<2> idx;
7581  let Inst{20-19} = idx;
7582  let Inst{18-16} = 0b100;
7583}
7584
7585class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7586                           RegisterOperand vecreg>
7587  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7588                       VectorIndexH, AArch64duplane16> {
7589  bits<3> idx;
7590  let Inst{20-18} = idx;
7591  let Inst{17-16} = 0b10;
7592}
7593
7594class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7595                          RegisterOperand vecreg>
7596  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7597                       VectorIndexB, AArch64duplane8> {
7598  bits<4> idx;
7599  let Inst{20-17} = idx;
7600  let Inst{16} = 1;
7601}
7602
7603class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7604                  Operand idxtype, string asm, list<dag> pattern>
7605  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7606                   "{\t$Rd, $Rn" # size # "$idx" #
7607                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7608  let Inst{14-11} = imm4;
7609}
7610
7611class SIMDSMov<bit Q, string size, RegisterClass regtype,
7612               Operand idxtype>
7613  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7614class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7615               Operand idxtype>
7616  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7617      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7618
7619class SIMDMovAlias<string asm, string size, Instruction inst,
7620                   RegisterClass regtype, Operand idxtype>
7621    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7622                    "|" # size # "\t$dst, $src$idx}",
7623                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7624
7625multiclass SMov {
7626  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7627  // streaming mode.
7628  let Predicates = [HasNEONorSME] in {
7629    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7630      let Inst{20-16} = 0b00001;
7631    }
7632    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7633      let Inst{20-16} = 0b00001;
7634    }
7635    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7636      let Inst{20-16} = 0b00010;
7637    }
7638    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7639      let Inst{20-16} = 0b00010;
7640    }
7641    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7642      let Inst{20-16} = 0b00100;
7643    }
7644  }
7645  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7646    bits<4> idx;
7647    let Inst{20-17} = idx;
7648    let Inst{16} = 1;
7649  }
7650  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7651    bits<4> idx;
7652    let Inst{20-17} = idx;
7653    let Inst{16} = 1;
7654  }
7655  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7656    bits<3> idx;
7657    let Inst{20-18} = idx;
7658    let Inst{17-16} = 0b10;
7659  }
7660  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7661    bits<3> idx;
7662    let Inst{20-18} = idx;
7663    let Inst{17-16} = 0b10;
7664  }
7665  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7666    bits<2> idx;
7667    let Inst{20-19} = idx;
7668    let Inst{18-16} = 0b100;
7669  }
7670}
7671
7672multiclass UMov {
7673  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7674  // streaming mode.
7675  let Predicates = [HasNEONorSME] in {
7676    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7677      let Inst{20-16} = 0b00001;
7678    }
7679    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7680      let Inst{20-16} = 0b00010;
7681    }
7682    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7683      let Inst{20-16} = 0b00100;
7684    }
7685    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7686      let Inst{20-16} = 0b01000;
7687    }
7688    def : SIMDMovAlias<"mov", ".s",
7689                       !cast<Instruction>(NAME # vi32_idx0),
7690                       GPR32, VectorIndex0>;
7691    def : SIMDMovAlias<"mov", ".d",
7692                       !cast<Instruction>(NAME # vi64_idx0),
7693                       GPR64, VectorIndex0>;
7694  }
7695  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7696    bits<4> idx;
7697    let Inst{20-17} = idx;
7698    let Inst{16} = 1;
7699  }
7700  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7701    bits<3> idx;
7702    let Inst{20-18} = idx;
7703    let Inst{17-16} = 0b10;
7704  }
7705  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7706    bits<2> idx;
7707    let Inst{20-19} = idx;
7708    let Inst{18-16} = 0b100;
7709  }
7710  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7711    bits<1> idx;
7712    let Inst{20} = idx;
7713    let Inst{19-16} = 0b1000;
7714  }
7715  def : SIMDMovAlias<"mov", ".s",
7716                     !cast<Instruction>(NAME#"vi32"),
7717                     GPR32, VectorIndexS>;
7718  def : SIMDMovAlias<"mov", ".d",
7719                     !cast<Instruction>(NAME#"vi64"),
7720                     GPR64, VectorIndexD>;
7721}
7722
7723class SIMDInsFromMain<string size, ValueType vectype,
7724                      RegisterClass regtype, Operand idxtype>
7725  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7726                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7727                   "{\t$Rd" # size # "$idx, $Rn" #
7728                   "|" # size # "\t$Rd$idx, $Rn}",
7729                   "$Rd = $dst",
7730            [(set V128:$dst,
7731              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7732  let Inst{14-11} = 0b0011;
7733}
7734
7735class SIMDInsFromElement<string size, ValueType vectype,
7736                         ValueType elttype, Operand idxtype>
7737  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7738                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7739                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7740                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7741                   "$Rd = $dst",
7742         [(set V128:$dst,
7743               (vector_insert
7744                 (vectype V128:$Rd),
7745                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7746                 idxtype:$idx))]>;
7747
7748class SIMDInsMainMovAlias<string size, Instruction inst,
7749                          RegisterClass regtype, Operand idxtype>
7750    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7751                        "|" # size #"\t$dst$idx, $src}",
7752                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7753class SIMDInsElementMovAlias<string size, Instruction inst,
7754                             Operand idxtype>
7755    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7756                      # "|" # size #"\t$dst$idx, $src$idx2}",
7757                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7758
7759
7760multiclass SIMDIns {
7761  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7762    bits<4> idx;
7763    let Inst{20-17} = idx;
7764    let Inst{16} = 1;
7765  }
7766  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7767    bits<3> idx;
7768    let Inst{20-18} = idx;
7769    let Inst{17-16} = 0b10;
7770  }
7771  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7772    bits<2> idx;
7773    let Inst{20-19} = idx;
7774    let Inst{18-16} = 0b100;
7775  }
7776  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7777    bits<1> idx;
7778    let Inst{20} = idx;
7779    let Inst{19-16} = 0b1000;
7780  }
7781
7782  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7783    bits<4> idx;
7784    bits<4> idx2;
7785    let Inst{20-17} = idx;
7786    let Inst{16} = 1;
7787    let Inst{14-11} = idx2;
7788  }
7789  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7790    bits<3> idx;
7791    bits<3> idx2;
7792    let Inst{20-18} = idx;
7793    let Inst{17-16} = 0b10;
7794    let Inst{14-12} = idx2;
7795    let Inst{11} = {?};
7796  }
7797  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7798    bits<2> idx;
7799    bits<2> idx2;
7800    let Inst{20-19} = idx;
7801    let Inst{18-16} = 0b100;
7802    let Inst{14-13} = idx2;
7803    let Inst{12-11} = {?,?};
7804  }
7805  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7806    bits<1> idx;
7807    bits<1> idx2;
7808    let Inst{20} = idx;
7809    let Inst{19-16} = 0b1000;
7810    let Inst{14} = idx2;
7811    let Inst{13-11} = {?,?,?};
7812  }
7813
7814  // For all forms of the INS instruction, the "mov" mnemonic is the
7815  // preferred alias. Why they didn't just call the instruction "mov" in
7816  // the first place is a very good question indeed...
7817  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7818                         GPR32, VectorIndexB>;
7819  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7820                         GPR32, VectorIndexH>;
7821  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7822                         GPR32, VectorIndexS>;
7823  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7824                         GPR64, VectorIndexD>;
7825
7826  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7827                         VectorIndexB>;
7828  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7829                         VectorIndexH>;
7830  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7831                         VectorIndexS>;
7832  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7833                         VectorIndexD>;
7834}
7835
7836//----------------------------------------------------------------------------
7837// AdvSIMD TBL/TBX
7838//----------------------------------------------------------------------------
7839
7840let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7841class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7842                          RegisterOperand listtype, string asm, string kind>
7843  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7844       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7845    Sched<[!if(Q, WriteVq, WriteVd)]> {
7846  bits<5> Vd;
7847  bits<5> Vn;
7848  bits<5> Vm;
7849  let Inst{31}    = 0;
7850  let Inst{30}    = Q;
7851  let Inst{29-21} = 0b001110000;
7852  let Inst{20-16} = Vm;
7853  let Inst{15}    = 0;
7854  let Inst{14-13} = len;
7855  let Inst{12}    = op;
7856  let Inst{11-10} = 0b00;
7857  let Inst{9-5}   = Vn;
7858  let Inst{4-0}   = Vd;
7859}
7860
7861let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7862class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7863                          RegisterOperand listtype, string asm, string kind>
7864  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7865       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7866    Sched<[!if(Q, WriteVq, WriteVd)]> {
7867  bits<5> Vd;
7868  bits<5> Vn;
7869  bits<5> Vm;
7870  let Inst{31}    = 0;
7871  let Inst{30}    = Q;
7872  let Inst{29-21} = 0b001110000;
7873  let Inst{20-16} = Vm;
7874  let Inst{15}    = 0;
7875  let Inst{14-13} = len;
7876  let Inst{12}    = op;
7877  let Inst{11-10} = 0b00;
7878  let Inst{9-5}   = Vn;
7879  let Inst{4-0}   = Vd;
7880}
7881
7882class SIMDTableLookupAlias<string asm, Instruction inst,
7883                          RegisterOperand vectype, RegisterOperand listtype>
7884    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7885                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7886
7887multiclass SIMDTableLookup<bit op, string asm> {
7888  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7889                                      asm, ".8b">;
7890  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7891                                      asm, ".8b">;
7892  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7893                                      asm, ".8b">;
7894  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7895                                      asm, ".8b">;
7896  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7897                                      asm, ".16b">;
7898  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7899                                      asm, ".16b">;
7900  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7901                                      asm, ".16b">;
7902  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7903                                      asm, ".16b">;
7904
7905  def : SIMDTableLookupAlias<asm # ".8b",
7906                         !cast<Instruction>(NAME#"v8i8One"),
7907                         V64, VecListOne128>;
7908  def : SIMDTableLookupAlias<asm # ".8b",
7909                         !cast<Instruction>(NAME#"v8i8Two"),
7910                         V64, VecListTwo128>;
7911  def : SIMDTableLookupAlias<asm # ".8b",
7912                         !cast<Instruction>(NAME#"v8i8Three"),
7913                         V64, VecListThree128>;
7914  def : SIMDTableLookupAlias<asm # ".8b",
7915                         !cast<Instruction>(NAME#"v8i8Four"),
7916                         V64, VecListFour128>;
7917  def : SIMDTableLookupAlias<asm # ".16b",
7918                         !cast<Instruction>(NAME#"v16i8One"),
7919                         V128, VecListOne128>;
7920  def : SIMDTableLookupAlias<asm # ".16b",
7921                         !cast<Instruction>(NAME#"v16i8Two"),
7922                         V128, VecListTwo128>;
7923  def : SIMDTableLookupAlias<asm # ".16b",
7924                         !cast<Instruction>(NAME#"v16i8Three"),
7925                         V128, VecListThree128>;
7926  def : SIMDTableLookupAlias<asm # ".16b",
7927                         !cast<Instruction>(NAME#"v16i8Four"),
7928                         V128, VecListFour128>;
7929}
7930
7931multiclass SIMDTableLookupTied<bit op, string asm> {
7932  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7933                                      asm, ".8b">;
7934  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7935                                      asm, ".8b">;
7936  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7937                                      asm, ".8b">;
7938  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7939                                      asm, ".8b">;
7940  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7941                                      asm, ".16b">;
7942  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7943                                      asm, ".16b">;
7944  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7945                                      asm, ".16b">;
7946  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7947                                      asm, ".16b">;
7948
7949  def : SIMDTableLookupAlias<asm # ".8b",
7950                         !cast<Instruction>(NAME#"v8i8One"),
7951                         V64, VecListOne128>;
7952  def : SIMDTableLookupAlias<asm # ".8b",
7953                         !cast<Instruction>(NAME#"v8i8Two"),
7954                         V64, VecListTwo128>;
7955  def : SIMDTableLookupAlias<asm # ".8b",
7956                         !cast<Instruction>(NAME#"v8i8Three"),
7957                         V64, VecListThree128>;
7958  def : SIMDTableLookupAlias<asm # ".8b",
7959                         !cast<Instruction>(NAME#"v8i8Four"),
7960                         V64, VecListFour128>;
7961  def : SIMDTableLookupAlias<asm # ".16b",
7962                         !cast<Instruction>(NAME#"v16i8One"),
7963                         V128, VecListOne128>;
7964  def : SIMDTableLookupAlias<asm # ".16b",
7965                         !cast<Instruction>(NAME#"v16i8Two"),
7966                         V128, VecListTwo128>;
7967  def : SIMDTableLookupAlias<asm # ".16b",
7968                         !cast<Instruction>(NAME#"v16i8Three"),
7969                         V128, VecListThree128>;
7970  def : SIMDTableLookupAlias<asm # ".16b",
7971                         !cast<Instruction>(NAME#"v16i8Four"),
7972                         V128, VecListFour128>;
7973}
7974
7975
7976//----------------------------------------------------------------------------
7977// AdvSIMD scalar DUP
7978//----------------------------------------------------------------------------
7979let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7980class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
7981                        string asm, string kind, Operand idxtype>
7982  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
7983       "{\t$dst, $src" # kind # "$idx" #
7984       "|\t$dst, $src$idx}", "", []>,
7985    Sched<[WriteVd]> {
7986  bits<5> dst;
7987  bits<5> src;
7988  let Inst{31-21} = 0b01011110000;
7989  let Inst{15-10} = 0b000001;
7990  let Inst{9-5}   = src;
7991  let Inst{4-0}   = dst;
7992}
7993
7994class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
7995      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7996    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7997                    # "|\t$dst, $src$index}",
7998                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7999
8000
8001multiclass SIMDScalarDUP<string asm> {
8002  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
8003    bits<4> idx;
8004    let Inst{20-17} = idx;
8005    let Inst{16} = 1;
8006  }
8007  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
8008    bits<3> idx;
8009    let Inst{20-18} = idx;
8010    let Inst{17-16} = 0b10;
8011  }
8012  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
8013    bits<2> idx;
8014    let Inst{20-19} = idx;
8015    let Inst{18-16} = 0b100;
8016  }
8017  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
8018    bits<1> idx;
8019    let Inst{20} = idx;
8020    let Inst{19-16} = 0b1000;
8021  }
8022
8023  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
8024                                                          VectorIndexD:$idx)))),
8025            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
8026
8027  // 'DUP' mnemonic aliases.
8028  def : SIMDScalarDUPAlias<"dup", ".b",
8029                           !cast<Instruction>(NAME#"i8"),
8030                           FPR8, V128, VectorIndexB>;
8031  def : SIMDScalarDUPAlias<"dup", ".h",
8032                           !cast<Instruction>(NAME#"i16"),
8033                           FPR16, V128, VectorIndexH>;
8034  def : SIMDScalarDUPAlias<"dup", ".s",
8035                           !cast<Instruction>(NAME#"i32"),
8036                           FPR32, V128, VectorIndexS>;
8037  def : SIMDScalarDUPAlias<"dup", ".d",
8038                           !cast<Instruction>(NAME#"i64"),
8039                           FPR64, V128, VectorIndexD>;
8040}
8041
8042//----------------------------------------------------------------------------
8043// AdvSIMD modified immediate instructions
8044//----------------------------------------------------------------------------
8045
8046class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
8047                          string asm, string op_string,
8048                          string cstr, list<dag> pattern>
8049  : I<oops, iops, asm, op_string, cstr, pattern>,
8050    Sched<[!if(Q, WriteVq, WriteVd)]> {
8051  bits<5> Rd;
8052  bits<8> imm8;
8053  let Inst{31}    = 0;
8054  let Inst{30}    = Q;
8055  let Inst{29}    = op;
8056  let Inst{28-19} = 0b0111100000;
8057  let Inst{18-16} = imm8{7-5};
8058  let Inst{11} = op2;
8059  let Inst{10} = 1;
8060  let Inst{9-5}   = imm8{4-0};
8061  let Inst{4-0}   = Rd;
8062}
8063
8064class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
8065                                Operand immtype, dag opt_shift_iop,
8066                                string opt_shift, string asm, string kind,
8067                                list<dag> pattern>
8068  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
8069                        !con((ins immtype:$imm8), opt_shift_iop), asm,
8070                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
8071                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8072                        "", pattern> {
8073  let DecoderMethod = "DecodeModImmInstruction";
8074}
8075
8076class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
8077                                Operand immtype, dag opt_shift_iop,
8078                                string opt_shift, string asm, string kind,
8079                                list<dag> pattern>
8080  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
8081                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
8082                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
8083                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8084                        "$Rd = $dst", pattern> {
8085  let DecoderMethod = "DecodeModImmTiedInstruction";
8086}
8087
8088class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
8089                                     RegisterOperand vectype, string asm,
8090                                     string kind, list<dag> pattern>
8091  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8092                              (ins logical_vec_shift:$shift),
8093                              "$shift", asm, kind, pattern> {
8094  bits<2> shift;
8095  let Inst{15}    = b15_b12{1};
8096  let Inst{14-13} = shift;
8097  let Inst{12}    = b15_b12{0};
8098}
8099
8100class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
8101                                     RegisterOperand vectype, string asm,
8102                                     string kind, list<dag> pattern>
8103  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8104                              (ins logical_vec_shift:$shift),
8105                              "$shift", asm, kind, pattern> {
8106  bits<2> shift;
8107  let Inst{15}    = b15_b12{1};
8108  let Inst{14-13} = shift;
8109  let Inst{12}    = b15_b12{0};
8110}
8111
8112
8113class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
8114                                         RegisterOperand vectype, string asm,
8115                                         string kind, list<dag> pattern>
8116  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8117                              (ins logical_vec_hw_shift:$shift),
8118                              "$shift", asm, kind, pattern> {
8119  bits<2> shift;
8120  let Inst{15} = b15_b12{1};
8121  let Inst{14} = 0;
8122  let Inst{13} = shift{0};
8123  let Inst{12} = b15_b12{0};
8124}
8125
8126class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
8127                                         RegisterOperand vectype, string asm,
8128                                         string kind, list<dag> pattern>
8129  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8130                              (ins logical_vec_hw_shift:$shift),
8131                              "$shift", asm, kind, pattern> {
8132  bits<2> shift;
8133  let Inst{15} = b15_b12{1};
8134  let Inst{14} = 0;
8135  let Inst{13} = shift{0};
8136  let Inst{12} = b15_b12{0};
8137}
8138
8139multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
8140                                      string asm> {
8141  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
8142                                                 asm, ".4h", []>;
8143  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
8144                                                 asm, ".8h", []>;
8145
8146  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
8147                                             asm, ".2s", []>;
8148  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
8149                                             asm, ".4s", []>;
8150}
8151
8152multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
8153                                      bits<2> w_cmode, string asm,
8154                                      SDNode OpNode> {
8155  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
8156                                                 asm, ".4h",
8157             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
8158                                             imm0_255:$imm8,
8159                                             (i32 imm:$shift)))]>;
8160  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
8161                                                 asm, ".8h",
8162             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
8163                                              imm0_255:$imm8,
8164                                              (i32 imm:$shift)))]>;
8165
8166  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
8167                                             asm, ".2s",
8168             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
8169                                             imm0_255:$imm8,
8170                                             (i32 imm:$shift)))]>;
8171  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
8172                                             asm, ".4s",
8173             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
8174                                              imm0_255:$imm8,
8175                                              (i32 imm:$shift)))]>;
8176}
8177
8178class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
8179                             RegisterOperand vectype, string asm,
8180                             string kind, list<dag> pattern>
8181  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8182                              (ins move_vec_shift:$shift),
8183                              "$shift", asm, kind, pattern> {
8184  bits<1> shift;
8185  let Inst{15-13} = cmode{3-1};
8186  let Inst{12}    = shift;
8187}
8188
8189class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
8190                                   RegisterOperand vectype,
8191                                   Operand imm_type, string asm,
8192                                   string kind, list<dag> pattern>
8193  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
8194                              asm, kind, pattern> {
8195  let Inst{15-12} = cmode;
8196}
8197
8198class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
8199                                   list<dag> pattern>
8200  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
8201                        "\t$Rd, $imm8", "", pattern> {
8202  let Inst{15-12} = cmode;
8203  let DecoderMethod = "DecodeModImmInstruction";
8204}
8205
8206//----------------------------------------------------------------------------
8207// AdvSIMD indexed element
8208//----------------------------------------------------------------------------
8209
8210let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8211class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8212                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8213                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8214                      string apple_kind, string dst_kind, string lhs_kind,
8215                      string rhs_kind, list<dag> pattern>
8216  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8217      asm,
8218      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8219      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8220    Sched<[WriteVd]> {
8221  bits<5> Rd;
8222  bits<5> Rn;
8223  bits<5> Rm;
8224
8225  let Inst{31}    = 0;
8226  let Inst{30}    = Q;
8227  let Inst{29}    = U;
8228  let Inst{28}    = Scalar;
8229  let Inst{27-24} = 0b1111;
8230  let Inst{23-22} = size;
8231  // Bit 21 must be set by the derived class.
8232  let Inst{20-16} = Rm;
8233  let Inst{15-12} = opc;
8234  // Bit 11 must be set by the derived class.
8235  let Inst{10}    = 0;
8236  let Inst{9-5}   = Rn;
8237  let Inst{4-0}   = Rd;
8238}
8239
8240let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8241class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8242                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8243                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8244                      string apple_kind, string dst_kind, string lhs_kind,
8245                      string rhs_kind, list<dag> pattern>
8246  : I<(outs dst_reg:$dst),
8247      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8248      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8249      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8250    Sched<[WriteVd]> {
8251  bits<5> Rd;
8252  bits<5> Rn;
8253  bits<5> Rm;
8254
8255  let Inst{31}    = 0;
8256  let Inst{30}    = Q;
8257  let Inst{29}    = U;
8258  let Inst{28}    = Scalar;
8259  let Inst{27-24} = 0b1111;
8260  let Inst{23-22} = size;
8261  // Bit 21 must be set by the derived class.
8262  let Inst{20-16} = Rm;
8263  let Inst{15-12} = opc;
8264  // Bit 11 must be set by the derived class.
8265  let Inst{10}    = 0;
8266  let Inst{9-5}   = Rn;
8267  let Inst{4-0}   = Rd;
8268}
8269
8270
8271//----------------------------------------------------------------------------
8272// Armv8.6 BFloat16 Extension
8273//----------------------------------------------------------------------------
8274let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8275
8276class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8277                                   string kind2, RegisterOperand RegType,
8278                                   ValueType AccumType, ValueType InputType>
8279  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8280                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8281                                            (InputType RegType:$Rn),
8282                                            (InputType RegType:$Rm)))]> {
8283  let AsmString = !strconcat(asm,
8284                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8285                               ", $Rm" # kind2 # "}");
8286}
8287
8288multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8289  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8290                                           v2f32, v4bf16>;
8291  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8292                                           v4f32, v8bf16>;
8293}
8294
8295class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8296                                      string dst_kind, string lhs_kind,
8297                                      string rhs_kind,
8298                                      RegisterOperand RegType,
8299                                      ValueType AccumType,
8300                                      ValueType InputType>
8301  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8302                        RegType, RegType, V128, VectorIndexS,
8303                        asm, "", dst_kind, lhs_kind, rhs_kind,
8304        [(set (AccumType RegType:$dst),
8305              (AccumType (int_aarch64_neon_bfdot
8306                                 (AccumType RegType:$Rd),
8307                                 (InputType RegType:$Rn),
8308                                 (InputType (bitconvert (AccumType
8309                                    (AArch64duplane32 (v4f32 V128:$Rm),
8310                                        VectorIndexS:$idx)))))))]> {
8311
8312  bits<2> idx;
8313  let Inst{21}    = idx{0};  // L
8314  let Inst{11}    = idx{1};  // H
8315}
8316
8317multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8318
8319  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8320                                               ".2h", V64, v2f32, v4bf16>;
8321  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8322                                              ".2h", V128, v4f32, v8bf16>;
8323}
8324
8325let mayRaiseFPException = 1, Uses = [FPCR] in
8326class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8327  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8328              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8329                                               (v8bf16 V128:$Rn),
8330                                               (v8bf16 V128:$Rm)))]> {
8331  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8332}
8333
8334let mayRaiseFPException = 1, Uses = [FPCR] in
8335class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8336  : I<(outs V128:$dst),
8337      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8338      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8339          [(set (v4f32 V128:$dst),
8340                (v4f32 (OpNode (v4f32 V128:$Rd),
8341                               (v8bf16 V128:$Rn),
8342                               (v8bf16
8343                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8344                                      VectorIndexH:$idx)))))]>,
8345    Sched<[WriteVq]> {
8346  bits<5> Rd;
8347  bits<5> Rn;
8348  bits<4> Rm;
8349  bits<3> idx;
8350
8351  let Inst{31}    = 0;
8352  let Inst{30}    = Q;
8353  let Inst{29-22} = 0b00111111;
8354  let Inst{21-20} = idx{1-0};
8355  let Inst{19-16} = Rm;
8356  let Inst{15-12} = 0b1111;
8357  let Inst{11}    = idx{2};   // H
8358  let Inst{10}    = 0;
8359  let Inst{9-5}   = Rn;
8360  let Inst{4-0}   = Rd;
8361}
8362
8363class SIMDThreeSameVectorBF16MatrixMul<string asm>
8364  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8365                                V128, asm, ".4s",
8366                          [(set (v4f32 V128:$dst),
8367                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8368                                                         (v8bf16 V128:$Rn),
8369                                                         (v8bf16 V128:$Rm)))]> {
8370  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8371                                    ", $Rm", ".8h", "}");
8372}
8373
8374let mayRaiseFPException = 1, Uses = [FPCR] in
8375class SIMD_BFCVTN
8376  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8377                           "bfcvtn", ".4h", ".4s",
8378    [(set (v8bf16 V128:$Rd),
8379          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8380
8381let mayRaiseFPException = 1, Uses = [FPCR] in
8382class SIMD_BFCVTN2
8383  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8384                           "bfcvtn2", ".8h", ".4s",
8385    [(set (v8bf16 V128:$dst),
8386          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8387
8388let mayRaiseFPException = 1, Uses = [FPCR] in
8389class BF16ToSinglePrecision<string asm>
8390  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8391    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8392    Sched<[WriteFCvt]> {
8393  bits<5> Rd;
8394  bits<5> Rn;
8395  let Inst{31-10} = 0b0001111001100011010000;
8396  let Inst{9-5}   = Rn;
8397  let Inst{4-0}   = Rd;
8398}
8399} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8400
8401//----------------------------------------------------------------------------
8402// Armv8.6 Matrix Multiply Extension
8403//----------------------------------------------------------------------------
8404
8405class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8406  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8407              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8408                                               (v16i8 V128:$Rn),
8409                                               (v16i8 V128:$Rm)))]> {
8410  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8411}
8412
8413//----------------------------------------------------------------------------
8414// ARMv8.2-A Dot Product Instructions (Indexed)
8415class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8416                                      string dst_kind, string lhs_kind, string rhs_kind,
8417                                      RegisterOperand RegType,
8418                                      ValueType AccumType, ValueType InputType,
8419                                      SDPatternOperator OpNode> :
8420        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8421                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8422        [(set (AccumType RegType:$dst),
8423              (AccumType (OpNode (AccumType RegType:$Rd),
8424                                 (InputType RegType:$Rn),
8425                                 (InputType (bitconvert (AccumType
8426                                    (AArch64duplane32 (v4i32 V128:$Rm),
8427                                        VectorIndexS:$idx)))))))]> {
8428  bits<2> idx;
8429  let Inst{21}    = idx{0};  // L
8430  let Inst{11}    = idx{1};  // H
8431}
8432
8433multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8434                                       SDPatternOperator OpNode> {
8435  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8436                                              V64, v2i32, v8i8, OpNode>;
8437  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8438                                              V128, v4i32, v16i8, OpNode>;
8439}
8440
8441// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8442let mayRaiseFPException = 1, Uses = [FPCR] in
8443class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8444                                      string dst_kind, string lhs_kind,
8445                                      string rhs_kind, RegisterOperand RegType,
8446                                      ValueType AccumType, ValueType InputType,
8447                                      SDPatternOperator OpNode> :
8448        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128_lo,
8449                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8450          [(set (AccumType RegType:$dst),
8451                (AccumType (OpNode (AccumType RegType:$Rd),
8452                                   (InputType RegType:$Rn),
8453                                   (InputType (AArch64duplane16 (v8f16 V128_lo:$Rm),
8454                                                VectorIndexH:$idx)))))]> {
8455  // idx = H:L:M
8456  bits<3> idx;
8457  let Inst{11} = idx{2}; // H
8458  let Inst{21} = idx{1}; // L
8459  let Inst{20} = idx{0}; // M
8460}
8461
8462multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8463                                       SDPatternOperator OpNode> {
8464  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8465                                              V64, v2f32, v4f16, OpNode>;
8466  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8467                                              V128, v4f32, v8f16, OpNode>;
8468}
8469
8470multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8471                         SDPatternOperator OpNode> {
8472  let mayRaiseFPException = 1, Uses = [FPCR] in {
8473  let Predicates = [HasNEON, HasFullFP16] in {
8474  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8475                                      V64, V64,
8476                                      V128_lo, VectorIndexH,
8477                                      asm, ".4h", ".4h", ".4h", ".h",
8478    [(set (v4f16 V64:$Rd),
8479        (OpNode (v4f16 V64:$Rn),
8480         (dup_v8f16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8481    bits<3> idx;
8482    let Inst{11} = idx{2};
8483    let Inst{21} = idx{1};
8484    let Inst{20} = idx{0};
8485  }
8486
8487  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8488                                      V128, V128,
8489                                      V128_lo, VectorIndexH,
8490                                      asm, ".8h", ".8h", ".8h", ".h",
8491    [(set (v8f16 V128:$Rd),
8492        (OpNode (v8f16 V128:$Rn),
8493         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8494    bits<3> idx;
8495    let Inst{11} = idx{2};
8496    let Inst{21} = idx{1};
8497    let Inst{20} = idx{0};
8498  }
8499  } // Predicates = [HasNEON, HasFullFP16]
8500
8501  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8502                                      V64, V64,
8503                                      V128, VectorIndexS,
8504                                      asm, ".2s", ".2s", ".2s", ".s",
8505    [(set (v2f32 V64:$Rd),
8506        (OpNode (v2f32 V64:$Rn),
8507         (dup_v4f32 (v4f32 V128:$Rm), VectorIndexS:$idx)))]> {
8508    bits<2> idx;
8509    let Inst{11} = idx{1};
8510    let Inst{21} = idx{0};
8511  }
8512
8513  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8514                                      V128, V128,
8515                                      V128, VectorIndexS,
8516                                      asm, ".4s", ".4s", ".4s", ".s",
8517    [(set (v4f32 V128:$Rd),
8518        (OpNode (v4f32 V128:$Rn),
8519         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8520    bits<2> idx;
8521    let Inst{11} = idx{1};
8522    let Inst{21} = idx{0};
8523  }
8524
8525  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8526                                      V128, V128,
8527                                      V128, VectorIndexD,
8528                                      asm, ".2d", ".2d", ".2d", ".d",
8529    [(set (v2f64 V128:$Rd),
8530        (OpNode (v2f64 V128:$Rn),
8531         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8532    bits<1> idx;
8533    let Inst{11} = idx{0};
8534    let Inst{21} = 0;
8535  }
8536
8537  let Predicates = [HasNEON, HasFullFP16] in {
8538  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8539                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8540                                      asm, ".h", "", "", ".h",
8541    [(set (f16 FPR16Op:$Rd),
8542          (OpNode (f16 FPR16Op:$Rn),
8543                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8544                                       VectorIndexH:$idx))))]> {
8545    bits<3> idx;
8546    let Inst{11} = idx{2};
8547    let Inst{21} = idx{1};
8548    let Inst{20} = idx{0};
8549  }
8550  } // Predicates = [HasNEON, HasFullFP16]
8551
8552  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8553                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8554                                      asm, ".s", "", "", ".s",
8555    [(set (f32 FPR32Op:$Rd),
8556          (OpNode (f32 FPR32Op:$Rn),
8557                  (f32 (vector_extract (v4f32 V128:$Rm),
8558                                       VectorIndexS:$idx))))]> {
8559    bits<2> idx;
8560    let Inst{11} = idx{1};
8561    let Inst{21} = idx{0};
8562  }
8563
8564  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8565                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8566                                      asm, ".d", "", "", ".d",
8567    [(set (f64 FPR64Op:$Rd),
8568          (OpNode (f64 FPR64Op:$Rn),
8569                  (f64 (vector_extract (v2f64 V128:$Rm),
8570                                       VectorIndexD:$idx))))]> {
8571    bits<1> idx;
8572    let Inst{11} = idx{0};
8573    let Inst{21} = 0;
8574  }
8575  } // mayRaiseFPException = 1, Uses = [FPCR]
8576
8577  let Predicates = [HasNEON, HasFullFP16] in {
8578  def : Pat<(f16 (OpNode
8579                   (f16 (vector_extract (v8f16 V128:$Rn), (i64 0))),
8580                   (f16 (vector_extract (v8f16 V128:$Rm), VectorIndexH:$idx)))),
8581            (!cast<Instruction>(NAME # v1i16_indexed)
8582              (EXTRACT_SUBREG V128:$Rn, hsub), V128:$Rm, VectorIndexH:$idx)>;
8583  }
8584
8585  let Predicates = [HasNEON] in {
8586  def : Pat<(f32 (OpNode
8587                   (f32 (vector_extract (v4f32 V128:$Rn), (i64 0))),
8588                   (f32 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx)))),
8589            (!cast<Instruction>(NAME # v1i32_indexed)
8590              (EXTRACT_SUBREG V128:$Rn, ssub), V128:$Rm, VectorIndexS:$idx)>;
8591
8592  def : Pat<(f64 (OpNode
8593                   (f64 (vector_extract (v2f64 V128:$Rn), (i64 0))),
8594                   (f64 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx)))),
8595            (!cast<Instruction>(NAME # v1i64_indexed)
8596              (EXTRACT_SUBREG V128:$Rn, dsub), V128:$Rm, VectorIndexD:$idx)>;
8597  }
8598}
8599
8600multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8601  let Predicates = [HasNEON, HasFullFP16] in {
8602  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8603  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8604                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8605                                           VectorIndexH:$idx))),
8606            (!cast<Instruction>(INST # "v8i16_indexed")
8607                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8608  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8609                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8610            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8611                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8612
8613  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8614                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8615                                           VectorIndexH:$idx))),
8616            (!cast<Instruction>(INST # "v4i16_indexed")
8617                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8618  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8619                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8620            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8621                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8622
8623  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8624                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8625            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8626                V128_lo:$Rm, VectorIndexH:$idx)>;
8627  } // Predicates = [HasNEON, HasFullFP16]
8628
8629  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8630  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8631                           (AArch64duplane32 (v4f32 V128:$Rm),
8632                                           VectorIndexS:$idx))),
8633            (!cast<Instruction>(INST # v2i32_indexed)
8634                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8635  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8636                           (AArch64dup (f32 FPR32Op:$Rm)))),
8637            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8638                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8639
8640
8641  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8642  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8643                           (AArch64duplane32 (v4f32 V128:$Rm),
8644                                           VectorIndexS:$idx))),
8645            (!cast<Instruction>(INST # "v4i32_indexed")
8646                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8647  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8648                           (AArch64dup (f32 FPR32Op:$Rm)))),
8649            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8650                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8651
8652  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8653  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8654                           (AArch64duplane64 (v2f64 V128:$Rm),
8655                                           VectorIndexD:$idx))),
8656            (!cast<Instruction>(INST # "v2i64_indexed")
8657                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8658  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8659                           (AArch64dup (f64 FPR64Op:$Rm)))),
8660            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8661                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8662
8663  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8664  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8665                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8666            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8667                V128:$Rm, VectorIndexS:$idx)>;
8668
8669  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8670  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8671                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8672            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8673                V128:$Rm, VectorIndexD:$idx)>;
8674}
8675
8676let mayRaiseFPException = 1, Uses = [FPCR] in
8677multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8678  let Predicates = [HasNEON, HasFullFP16] in {
8679  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8680                                          V128_lo, VectorIndexH,
8681                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8682    bits<3> idx;
8683    let Inst{11} = idx{2};
8684    let Inst{21} = idx{1};
8685    let Inst{20} = idx{0};
8686  }
8687
8688  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8689                                          V128, V128,
8690                                          V128_lo, VectorIndexH,
8691                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8692    bits<3> idx;
8693    let Inst{11} = idx{2};
8694    let Inst{21} = idx{1};
8695    let Inst{20} = idx{0};
8696  }
8697  } // Predicates = [HasNEON, HasFullFP16]
8698
8699  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8700                                          V128, VectorIndexS,
8701                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8702    bits<2> idx;
8703    let Inst{11} = idx{1};
8704    let Inst{21} = idx{0};
8705  }
8706
8707  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8708                                      V128, V128,
8709                                      V128, VectorIndexS,
8710                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8711    bits<2> idx;
8712    let Inst{11} = idx{1};
8713    let Inst{21} = idx{0};
8714  }
8715
8716  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8717                                      V128, V128,
8718                                      V128, VectorIndexD,
8719                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8720    bits<1> idx;
8721    let Inst{11} = idx{0};
8722    let Inst{21} = 0;
8723  }
8724
8725  let Predicates = [HasNEON, HasFullFP16] in {
8726  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8727                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8728                                      asm, ".h", "", "", ".h", []> {
8729    bits<3> idx;
8730    let Inst{11} = idx{2};
8731    let Inst{21} = idx{1};
8732    let Inst{20} = idx{0};
8733  }
8734  } // Predicates = [HasNEON, HasFullFP16]
8735
8736  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8737                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8738                                      asm, ".s", "", "", ".s", []> {
8739    bits<2> idx;
8740    let Inst{11} = idx{1};
8741    let Inst{21} = idx{0};
8742  }
8743
8744  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8745                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8746                                      asm, ".d", "", "", ".d", []> {
8747    bits<1> idx;
8748    let Inst{11} = idx{0};
8749    let Inst{21} = 0;
8750  }
8751}
8752
8753multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8754                                 SDPatternOperator OpNodeLaneQ> {
8755
8756  def : Pat<(v4i16 (OpNodeLane
8757                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8758                     VectorIndexS32b:$idx)),
8759            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8760              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8761              (UImmS1XForm $idx))>;
8762
8763  def : Pat<(v4i16 (OpNodeLaneQ
8764                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8765                     VectorIndexH32b:$idx)),
8766            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8767              (UImmS1XForm $idx))>;
8768
8769  def : Pat<(v8i16 (OpNodeLane
8770                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8771                     VectorIndexS32b:$idx)),
8772            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8773              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8774              (UImmS1XForm $idx))>;
8775
8776  def : Pat<(v8i16 (OpNodeLaneQ
8777                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8778                     VectorIndexH32b:$idx)),
8779            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8780              (UImmS1XForm $idx))>;
8781
8782  def : Pat<(v2i32 (OpNodeLane
8783                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8784                     VectorIndexD32b:$idx)),
8785            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8786              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8787              (UImmS1XForm $idx))>;
8788
8789  def : Pat<(v2i32 (OpNodeLaneQ
8790                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8791                     VectorIndexS32b:$idx)),
8792            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8793              (UImmS1XForm $idx))>;
8794
8795  def : Pat<(v4i32 (OpNodeLane
8796                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8797                     VectorIndexD32b:$idx)),
8798            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8799              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8800              (UImmS1XForm $idx))>;
8801
8802  def : Pat<(v4i32 (OpNodeLaneQ
8803                     (v4i32 V128:$Rn),
8804                     (v4i32 V128:$Rm),
8805                     VectorIndexS32b:$idx)),
8806            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8807              (UImmS1XForm $idx))>;
8808
8809}
8810
8811multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8812                         SDPatternOperator OpNode> {
8813  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8814                                      V128_lo, VectorIndexH,
8815                                      asm, ".4h", ".4h", ".4h", ".h",
8816    [(set (v4i16 V64:$Rd),
8817        (OpNode (v4i16 V64:$Rn),
8818         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8819    bits<3> idx;
8820    let Inst{11} = idx{2};
8821    let Inst{21} = idx{1};
8822    let Inst{20} = idx{0};
8823  }
8824
8825  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8826                                      V128, V128,
8827                                      V128_lo, VectorIndexH,
8828                                      asm, ".8h", ".8h", ".8h", ".h",
8829    [(set (v8i16 V128:$Rd),
8830       (OpNode (v8i16 V128:$Rn),
8831         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8832    bits<3> idx;
8833    let Inst{11} = idx{2};
8834    let Inst{21} = idx{1};
8835    let Inst{20} = idx{0};
8836  }
8837
8838  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8839                                      V64, V64,
8840                                      V128, VectorIndexS,
8841                                      asm, ".2s", ".2s", ".2s",  ".s",
8842    [(set (v2i32 V64:$Rd),
8843       (OpNode (v2i32 V64:$Rn),
8844          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8845    bits<2> idx;
8846    let Inst{11} = idx{1};
8847    let Inst{21} = idx{0};
8848  }
8849
8850  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8851                                      V128, V128,
8852                                      V128, VectorIndexS,
8853                                      asm, ".4s", ".4s", ".4s", ".s",
8854    [(set (v4i32 V128:$Rd),
8855       (OpNode (v4i32 V128:$Rn),
8856          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8857    bits<2> idx;
8858    let Inst{11} = idx{1};
8859    let Inst{21} = idx{0};
8860  }
8861
8862  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8863                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8864                                      asm, ".h", "", "", ".h", []> {
8865    bits<3> idx;
8866    let Inst{11} = idx{2};
8867    let Inst{21} = idx{1};
8868    let Inst{20} = idx{0};
8869  }
8870
8871  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8872                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8873                                      asm, ".s", "", "", ".s",
8874      [(set (i32 FPR32Op:$Rd),
8875            (OpNode FPR32Op:$Rn,
8876                    (i32 (vector_extract (v4i32 V128:$Rm),
8877                                         VectorIndexS:$idx))))]> {
8878    bits<2> idx;
8879    let Inst{11} = idx{1};
8880    let Inst{21} = idx{0};
8881  }
8882}
8883
8884multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8885                               SDPatternOperator OpNode> {
8886  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8887                                      V64, V64,
8888                                      V128_lo, VectorIndexH,
8889                                      asm, ".4h", ".4h", ".4h", ".h",
8890    [(set (v4i16 V64:$Rd),
8891        (OpNode (v4i16 V64:$Rn),
8892         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8893    bits<3> idx;
8894    let Inst{11} = idx{2};
8895    let Inst{21} = idx{1};
8896    let Inst{20} = idx{0};
8897  }
8898
8899  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8900                                      V128, V128,
8901                                      V128_lo, VectorIndexH,
8902                                      asm, ".8h", ".8h", ".8h", ".h",
8903    [(set (v8i16 V128:$Rd),
8904       (OpNode (v8i16 V128:$Rn),
8905         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8906    bits<3> idx;
8907    let Inst{11} = idx{2};
8908    let Inst{21} = idx{1};
8909    let Inst{20} = idx{0};
8910  }
8911
8912  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8913                                      V64, V64,
8914                                      V128, VectorIndexS,
8915                                      asm, ".2s", ".2s", ".2s", ".s",
8916    [(set (v2i32 V64:$Rd),
8917       (OpNode (v2i32 V64:$Rn),
8918          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8919    bits<2> idx;
8920    let Inst{11} = idx{1};
8921    let Inst{21} = idx{0};
8922  }
8923
8924  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8925                                      V128, V128,
8926                                      V128, VectorIndexS,
8927                                      asm, ".4s", ".4s", ".4s", ".s",
8928    [(set (v4i32 V128:$Rd),
8929       (OpNode (v4i32 V128:$Rn),
8930          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8931    bits<2> idx;
8932    let Inst{11} = idx{1};
8933    let Inst{21} = idx{0};
8934  }
8935}
8936
8937multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8938                                   SDPatternOperator OpNode> {
8939  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8940                                          V128_lo, VectorIndexH,
8941                                          asm, ".4h", ".4h", ".4h", ".h",
8942    [(set (v4i16 V64:$dst),
8943        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8944         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8945    bits<3> idx;
8946    let Inst{11} = idx{2};
8947    let Inst{21} = idx{1};
8948    let Inst{20} = idx{0};
8949  }
8950
8951  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8952                                      V128, V128,
8953                                      V128_lo, VectorIndexH,
8954                                      asm, ".8h", ".8h", ".8h", ".h",
8955    [(set (v8i16 V128:$dst),
8956       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8957         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8958    bits<3> idx;
8959    let Inst{11} = idx{2};
8960    let Inst{21} = idx{1};
8961    let Inst{20} = idx{0};
8962  }
8963
8964  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8965                                      V64, V64,
8966                                      V128, VectorIndexS,
8967                                      asm, ".2s", ".2s", ".2s", ".s",
8968    [(set (v2i32 V64:$dst),
8969       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8970          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8971    bits<2> idx;
8972    let Inst{11} = idx{1};
8973    let Inst{21} = idx{0};
8974  }
8975
8976  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8977                                      V128, V128,
8978                                      V128, VectorIndexS,
8979                                      asm, ".4s", ".4s", ".4s", ".s",
8980    [(set (v4i32 V128:$dst),
8981       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8982          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8983    bits<2> idx;
8984    let Inst{11} = idx{1};
8985    let Inst{21} = idx{0};
8986  }
8987}
8988
8989multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8990                             SDPatternOperator OpNode> {
8991  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8992                                      V128, V64,
8993                                      V128_lo, VectorIndexH,
8994                                      asm, ".4s", ".4s", ".4h", ".h",
8995    [(set (v4i32 V128:$Rd),
8996        (OpNode (v4i16 V64:$Rn),
8997         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8998    bits<3> idx;
8999    let Inst{11} = idx{2};
9000    let Inst{21} = idx{1};
9001    let Inst{20} = idx{0};
9002  }
9003
9004  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9005                                      V128, V128,
9006                                      V128_lo, VectorIndexH,
9007                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9008    [(set (v4i32 V128:$Rd),
9009          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9010                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9011
9012    bits<3> idx;
9013    let Inst{11} = idx{2};
9014    let Inst{21} = idx{1};
9015    let Inst{20} = idx{0};
9016  }
9017
9018  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9019                                      V128, V64,
9020                                      V128, VectorIndexS,
9021                                      asm, ".2d", ".2d", ".2s", ".s",
9022    [(set (v2i64 V128:$Rd),
9023        (OpNode (v2i32 V64:$Rn),
9024         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9025    bits<2> idx;
9026    let Inst{11} = idx{1};
9027    let Inst{21} = idx{0};
9028  }
9029
9030  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9031                                      V128, V128,
9032                                      V128, VectorIndexS,
9033                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9034    [(set (v2i64 V128:$Rd),
9035          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9036                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9037    bits<2> idx;
9038    let Inst{11} = idx{1};
9039    let Inst{21} = idx{0};
9040  }
9041
9042  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9043                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9044                                      asm, ".h", "", "", ".h", []> {
9045    bits<3> idx;
9046    let Inst{11} = idx{2};
9047    let Inst{21} = idx{1};
9048    let Inst{20} = idx{0};
9049  }
9050
9051  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9052                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9053                                      asm, ".s", "", "", ".s", []> {
9054    bits<2> idx;
9055    let Inst{11} = idx{1};
9056    let Inst{21} = idx{0};
9057  }
9058}
9059
9060multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
9061                                       SDPatternOperator Accum> {
9062  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9063                                      V128, V64,
9064                                      V128_lo, VectorIndexH,
9065                                      asm, ".4s", ".4s", ".4h", ".h",
9066    [(set (v4i32 V128:$dst),
9067          (Accum (v4i32 V128:$Rd),
9068                 (v4i32 (int_aarch64_neon_sqdmull
9069                             (v4i16 V64:$Rn),
9070                             (dup_v8i16 (v8i16 V128_lo:$Rm),
9071                                         VectorIndexH:$idx)))))]> {
9072    bits<3> idx;
9073    let Inst{11} = idx{2};
9074    let Inst{21} = idx{1};
9075    let Inst{20} = idx{0};
9076  }
9077
9078  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9079                                      V128, V128,
9080                                      V128_lo, VectorIndexH,
9081                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9082    [(set (v4i32 V128:$dst),
9083          (Accum (v4i32 V128:$Rd),
9084                 (v4i32 (int_aarch64_neon_sqdmull
9085                            (extract_high_v8i16 (v8i16 V128:$Rn)),
9086                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
9087    bits<3> idx;
9088    let Inst{11} = idx{2};
9089    let Inst{21} = idx{1};
9090    let Inst{20} = idx{0};
9091  }
9092
9093  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9094                                      V128, V64,
9095                                      V128, VectorIndexS,
9096                                      asm, ".2d", ".2d", ".2s", ".s",
9097    [(set (v2i64 V128:$dst),
9098        (Accum (v2i64 V128:$Rd),
9099               (v2i64 (int_aarch64_neon_sqdmull
9100                          (v2i32 V64:$Rn),
9101                          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9102    bits<2> idx;
9103    let Inst{11} = idx{1};
9104    let Inst{21} = idx{0};
9105  }
9106
9107  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9108                                      V128, V128,
9109                                      V128, VectorIndexS,
9110                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9111    [(set (v2i64 V128:$dst),
9112          (Accum (v2i64 V128:$Rd),
9113                 (v2i64 (int_aarch64_neon_sqdmull
9114                            (extract_high_v4i32 (v4i32 V128:$Rn)),
9115                            (extract_high_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 v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9122                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9123                                      asm, ".h", "", "", ".h", []> {
9124    bits<3> idx;
9125    let Inst{11} = idx{2};
9126    let Inst{21} = idx{1};
9127    let Inst{20} = idx{0};
9128  }
9129
9130  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9131                        (i32 (vector_extract
9132                                    (v4i32 (int_aarch64_neon_sqdmull
9133                                                (v4i16 V64:$Rn),
9134                                                (v4i16 V64:$Rm))),
9135                                    (i64 0))))),
9136            (!cast<Instruction>(NAME # v1i32_indexed)
9137                        FPR32Op:$Rd,
9138                        (EXTRACT_SUBREG V64:$Rn, hsub),
9139                        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rm, dsub),
9140                        (i64 0))>;
9141
9142  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9143                        (i32 (vector_extract
9144                                    (v4i32 (int_aarch64_neon_sqdmull
9145                                                (v4i16 V64:$Rn),
9146                                                (dup_v8i16 (v8i16 V128_lo:$Rm),
9147                                                            VectorIndexH:$idx))),
9148                                    (i64 0))))),
9149            (!cast<Instruction>(NAME # v1i32_indexed)
9150                        FPR32Op:$Rd,
9151                        (EXTRACT_SUBREG V64:$Rn, hsub),
9152                        V128_lo:$Rm,
9153                        VectorIndexH:$idx)>;
9154
9155  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9156                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9157                                      asm, ".s", "", "", ".s",
9158    [(set (i64 FPR64Op:$dst),
9159          (Accum (i64 FPR64Op:$Rd),
9160                 (i64 (int_aarch64_neon_sqdmulls_scalar
9161                            (i32 FPR32Op:$Rn),
9162                            (i32 (vector_extract (v4i32 V128:$Rm),
9163                                                 VectorIndexS:$idx))))))]> {
9164
9165    bits<2> idx;
9166    let Inst{11} = idx{1};
9167    let Inst{21} = idx{0};
9168  }
9169}
9170
9171multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
9172                                   SDPatternOperator OpNode> {
9173  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9174  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9175                                      V128, V64,
9176                                      V128_lo, VectorIndexH,
9177                                      asm, ".4s", ".4s", ".4h", ".h",
9178    [(set (v4i32 V128:$Rd),
9179        (OpNode (v4i16 V64:$Rn),
9180         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9181    bits<3> idx;
9182    let Inst{11} = idx{2};
9183    let Inst{21} = idx{1};
9184    let Inst{20} = idx{0};
9185  }
9186
9187  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9188                                      V128, V128,
9189                                      V128_lo, VectorIndexH,
9190                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9191    [(set (v4i32 V128:$Rd),
9192          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9193                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9194
9195    bits<3> idx;
9196    let Inst{11} = idx{2};
9197    let Inst{21} = idx{1};
9198    let Inst{20} = idx{0};
9199  }
9200
9201  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9202                                      V128, V64,
9203                                      V128, VectorIndexS,
9204                                      asm, ".2d", ".2d", ".2s", ".s",
9205    [(set (v2i64 V128:$Rd),
9206        (OpNode (v2i32 V64:$Rn),
9207         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9208    bits<2> idx;
9209    let Inst{11} = idx{1};
9210    let Inst{21} = idx{0};
9211  }
9212
9213  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9214                                      V128, V128,
9215                                      V128, VectorIndexS,
9216                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9217    [(set (v2i64 V128:$Rd),
9218          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9219                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9220    bits<2> idx;
9221    let Inst{11} = idx{1};
9222    let Inst{21} = idx{0};
9223  }
9224  }
9225}
9226
9227multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
9228                                       SDPatternOperator OpNode> {
9229  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9230  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9231                                      V128, V64,
9232                                      V128_lo, VectorIndexH,
9233                                      asm, ".4s", ".4s", ".4h", ".h",
9234    [(set (v4i32 V128:$dst),
9235        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
9236         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9237    bits<3> idx;
9238    let Inst{11} = idx{2};
9239    let Inst{21} = idx{1};
9240    let Inst{20} = idx{0};
9241  }
9242
9243  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9244                                      V128, V128,
9245                                      V128_lo, VectorIndexH,
9246                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9247    [(set (v4i32 V128:$dst),
9248          (OpNode (v4i32 V128:$Rd),
9249                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9250                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9251    bits<3> idx;
9252    let Inst{11} = idx{2};
9253    let Inst{21} = idx{1};
9254    let Inst{20} = idx{0};
9255  }
9256
9257  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9258                                      V128, V64,
9259                                      V128, VectorIndexS,
9260                                      asm, ".2d", ".2d", ".2s", ".s",
9261    [(set (v2i64 V128:$dst),
9262        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9263         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9264    bits<2> idx;
9265    let Inst{11} = idx{1};
9266    let Inst{21} = idx{0};
9267  }
9268
9269  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9270                                      V128, V128,
9271                                      V128, VectorIndexS,
9272                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9273    [(set (v2i64 V128:$dst),
9274          (OpNode (v2i64 V128:$Rd),
9275                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9276                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9277    bits<2> idx;
9278    let Inst{11} = idx{1};
9279    let Inst{21} = idx{0};
9280  }
9281  }
9282}
9283
9284//----------------------------------------------------------------------------
9285// AdvSIMD scalar shift by immediate
9286//----------------------------------------------------------------------------
9287
9288let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9289class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9290                     RegisterClass regtype1, RegisterClass regtype2,
9291                     Operand immtype, string asm, list<dag> pattern>
9292  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9293      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9294    Sched<[WriteVd]> {
9295  bits<5> Rd;
9296  bits<5> Rn;
9297  bits<7> imm;
9298  let Inst{31-30} = 0b01;
9299  let Inst{29}    = U;
9300  let Inst{28-23} = 0b111110;
9301  let Inst{22-16} = fixed_imm;
9302  let Inst{15-11} = opc;
9303  let Inst{10}    = 1;
9304  let Inst{9-5} = Rn;
9305  let Inst{4-0} = Rd;
9306}
9307
9308let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9309class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9310                     RegisterClass regtype1, RegisterClass regtype2,
9311                     Operand immtype, string asm, list<dag> pattern>
9312  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9313      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9314    Sched<[WriteVd]> {
9315  bits<5> Rd;
9316  bits<5> Rn;
9317  bits<7> imm;
9318  let Inst{31-30} = 0b01;
9319  let Inst{29}    = U;
9320  let Inst{28-23} = 0b111110;
9321  let Inst{22-16} = fixed_imm;
9322  let Inst{15-11} = opc;
9323  let Inst{10}    = 1;
9324  let Inst{9-5} = Rn;
9325  let Inst{4-0} = Rd;
9326}
9327
9328
9329multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9330  let Predicates = [HasNEON, HasFullFP16] in {
9331  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9332                              FPR16, FPR16, vecshiftR16, asm, []> {
9333    let Inst{19-16} = imm{3-0};
9334  }
9335  } // Predicates = [HasNEON, HasFullFP16]
9336  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9337                              FPR32, FPR32, vecshiftR32, asm, []> {
9338    let Inst{20-16} = imm{4-0};
9339  }
9340  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9341                              FPR64, FPR64, vecshiftR64, asm, []> {
9342    let Inst{21-16} = imm{5-0};
9343  }
9344}
9345
9346multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9347                             SDPatternOperator OpNode> {
9348  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9349                              FPR64, FPR64, vecshiftR64, asm,
9350  [(set (i64 FPR64:$Rd),
9351     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9352    let Inst{21-16} = imm{5-0};
9353  }
9354
9355  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9356            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9357}
9358
9359multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9360                                 SDPatternOperator OpNode = null_frag> {
9361  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9362                              FPR64, FPR64, vecshiftR64, asm,
9363  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9364                                                   (i32 vecshiftR64:$imm)))]> {
9365    let Inst{21-16} = imm{5-0};
9366  }
9367
9368  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9369                           (i32 vecshiftR64:$imm))),
9370            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9371                                            vecshiftR64:$imm)>;
9372}
9373
9374multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9375                             SDPatternOperator OpNode> {
9376  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9377                              FPR64, FPR64, vecshiftL64, asm,
9378    [(set (i64 FPR64:$Rd),
9379       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9380    let Inst{21-16} = imm{5-0};
9381  }
9382
9383  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9384            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9385}
9386
9387let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9388multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9389  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9390                              FPR64, FPR64, vecshiftL64, asm, []> {
9391    let Inst{21-16} = imm{5-0};
9392  }
9393}
9394
9395let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9396multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9397                               SDPatternOperator OpNode = null_frag> {
9398  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9399                              FPR8, FPR16, vecshiftR8, asm, []> {
9400    let Inst{18-16} = imm{2-0};
9401  }
9402
9403  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9404                              FPR16, FPR32, vecshiftR16, asm, []> {
9405    let Inst{19-16} = imm{3-0};
9406  }
9407
9408  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9409                              FPR32, FPR64, vecshiftR32, asm,
9410    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9411    let Inst{20-16} = imm{4-0};
9412  }
9413}
9414
9415multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9416                                SDPatternOperator OpNode> {
9417  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9418                              FPR8, FPR8, vecshiftL8, asm, []> {
9419    let Inst{18-16} = imm{2-0};
9420  }
9421
9422  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9423                              FPR16, FPR16, vecshiftL16, asm, []> {
9424    let Inst{19-16} = imm{3-0};
9425  }
9426
9427  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9428                              FPR32, FPR32, vecshiftL32, asm,
9429    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9430    let Inst{20-16} = imm{4-0};
9431  }
9432
9433  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9434                              FPR64, FPR64, vecshiftL64, asm,
9435    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9436    let Inst{21-16} = imm{5-0};
9437  }
9438
9439  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9440            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9441}
9442
9443multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9444  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9445                              FPR8, FPR8, vecshiftR8, asm, []> {
9446    let Inst{18-16} = imm{2-0};
9447  }
9448
9449  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9450                              FPR16, FPR16, vecshiftR16, asm, []> {
9451    let Inst{19-16} = imm{3-0};
9452  }
9453
9454  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9455                              FPR32, FPR32, vecshiftR32, asm, []> {
9456    let Inst{20-16} = imm{4-0};
9457  }
9458
9459  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9460                              FPR64, FPR64, vecshiftR64, asm, []> {
9461    let Inst{21-16} = imm{5-0};
9462  }
9463}
9464
9465//----------------------------------------------------------------------------
9466// AdvSIMD vector x indexed element
9467//----------------------------------------------------------------------------
9468
9469let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9470class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9471                     RegisterOperand dst_reg, RegisterOperand src_reg,
9472                     Operand immtype,
9473                     string asm, string dst_kind, string src_kind,
9474                     list<dag> pattern>
9475  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9476      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9477           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9478    Sched<[!if(Q, WriteVq, WriteVd)]> {
9479  bits<5> Rd;
9480  bits<5> Rn;
9481  let Inst{31}    = 0;
9482  let Inst{30}    = Q;
9483  let Inst{29}    = U;
9484  let Inst{28-23} = 0b011110;
9485  let Inst{22-16} = fixed_imm;
9486  let Inst{15-11} = opc;
9487  let Inst{10}    = 1;
9488  let Inst{9-5}   = Rn;
9489  let Inst{4-0}   = Rd;
9490}
9491
9492let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9493class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9494                     RegisterOperand vectype1, RegisterOperand vectype2,
9495                     Operand immtype,
9496                     string asm, string dst_kind, string src_kind,
9497                     list<dag> pattern>
9498  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9499      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9500           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9501    Sched<[!if(Q, WriteVq, WriteVd)]> {
9502  bits<5> Rd;
9503  bits<5> Rn;
9504  let Inst{31}    = 0;
9505  let Inst{30}    = Q;
9506  let Inst{29}    = U;
9507  let Inst{28-23} = 0b011110;
9508  let Inst{22-16} = fixed_imm;
9509  let Inst{15-11} = opc;
9510  let Inst{10}    = 1;
9511  let Inst{9-5}   = Rn;
9512  let Inst{4-0}   = Rd;
9513}
9514
9515multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9516                              Intrinsic OpNode> {
9517  let Predicates = [HasNEON, HasFullFP16] in {
9518  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9519                                  V64, V64, vecshiftR16,
9520                                  asm, ".4h", ".4h",
9521      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9522    bits<4> imm;
9523    let Inst{19-16} = imm;
9524  }
9525
9526  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9527                                  V128, V128, vecshiftR16,
9528                                  asm, ".8h", ".8h",
9529      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9530    bits<4> imm;
9531    let Inst{19-16} = imm;
9532  }
9533  } // Predicates = [HasNEON, HasFullFP16]
9534  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9535                                  V64, V64, vecshiftR32,
9536                                  asm, ".2s", ".2s",
9537      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9538    bits<5> imm;
9539    let Inst{20-16} = imm;
9540  }
9541
9542  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9543                                  V128, V128, vecshiftR32,
9544                                  asm, ".4s", ".4s",
9545      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9546    bits<5> imm;
9547    let Inst{20-16} = imm;
9548  }
9549
9550  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9551                                  V128, V128, vecshiftR64,
9552                                  asm, ".2d", ".2d",
9553      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9554    bits<6> imm;
9555    let Inst{21-16} = imm;
9556  }
9557}
9558
9559multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9560                                  Intrinsic OpNode> {
9561  let Predicates = [HasNEON, HasFullFP16] in {
9562  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9563                                  V64, V64, vecshiftR16,
9564                                  asm, ".4h", ".4h",
9565      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9566    bits<4> imm;
9567    let Inst{19-16} = imm;
9568  }
9569
9570  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9571                                  V128, V128, vecshiftR16,
9572                                  asm, ".8h", ".8h",
9573      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9574    bits<4> imm;
9575    let Inst{19-16} = imm;
9576  }
9577  } // Predicates = [HasNEON, HasFullFP16]
9578
9579  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9580                                  V64, V64, vecshiftR32,
9581                                  asm, ".2s", ".2s",
9582      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9583    bits<5> imm;
9584    let Inst{20-16} = imm;
9585  }
9586
9587  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9588                                  V128, V128, vecshiftR32,
9589                                  asm, ".4s", ".4s",
9590      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9591    bits<5> imm;
9592    let Inst{20-16} = imm;
9593  }
9594
9595  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9596                                  V128, V128, vecshiftR64,
9597                                  asm, ".2d", ".2d",
9598      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9599    bits<6> imm;
9600    let Inst{21-16} = imm;
9601  }
9602}
9603
9604multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9605                                     SDPatternOperator OpNode> {
9606  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9607                                  V64, V128, vecshiftR16Narrow,
9608                                  asm, ".8b", ".8h",
9609      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9610    bits<3> imm;
9611    let Inst{18-16} = imm;
9612  }
9613
9614  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9615                                  V128, V128, vecshiftR16Narrow,
9616                                  asm#"2", ".16b", ".8h", []> {
9617    bits<3> imm;
9618    let Inst{18-16} = imm;
9619    let hasSideEffects = 0;
9620  }
9621
9622  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9623                                  V64, V128, vecshiftR32Narrow,
9624                                  asm, ".4h", ".4s",
9625      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9626    bits<4> imm;
9627    let Inst{19-16} = imm;
9628  }
9629
9630  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9631                                  V128, V128, vecshiftR32Narrow,
9632                                  asm#"2", ".8h", ".4s", []> {
9633    bits<4> imm;
9634    let Inst{19-16} = imm;
9635    let hasSideEffects = 0;
9636  }
9637
9638  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9639                                  V64, V128, vecshiftR64Narrow,
9640                                  asm, ".2s", ".2d",
9641      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9642    bits<5> imm;
9643    let Inst{20-16} = imm;
9644  }
9645
9646  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9647                                  V128, V128, vecshiftR64Narrow,
9648                                  asm#"2", ".4s", ".2d", []> {
9649    bits<5> imm;
9650    let Inst{20-16} = imm;
9651    let hasSideEffects = 0;
9652  }
9653
9654  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9655  // themselves, so put them here instead.
9656
9657  // Patterns involving what's effectively an insert high and a normal
9658  // intrinsic, represented by CONCAT_VECTORS.
9659  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9660                                                   vecshiftR16Narrow:$imm)),
9661            (!cast<Instruction>(NAME # "v16i8_shift")
9662                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9663                V128:$Rn, vecshiftR16Narrow:$imm)>;
9664  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9665                                                     vecshiftR32Narrow:$imm)),
9666            (!cast<Instruction>(NAME # "v8i16_shift")
9667                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9668                V128:$Rn, vecshiftR32Narrow:$imm)>;
9669  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9670                                                     vecshiftR64Narrow:$imm)),
9671            (!cast<Instruction>(NAME # "v4i32_shift")
9672                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9673                V128:$Rn, vecshiftR64Narrow:$imm)>;
9674}
9675
9676multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9677                                SDPatternOperator OpNode> {
9678  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9679                                  V64, V64, vecshiftL8,
9680                                  asm, ".8b", ".8b",
9681                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9682                       (i32 vecshiftL8:$imm)))]> {
9683    bits<3> imm;
9684    let Inst{18-16} = imm;
9685  }
9686
9687  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9688                                  V128, V128, vecshiftL8,
9689                                  asm, ".16b", ".16b",
9690             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9691                   (i32 vecshiftL8:$imm)))]> {
9692    bits<3> imm;
9693    let Inst{18-16} = imm;
9694  }
9695
9696  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9697                                  V64, V64, vecshiftL16,
9698                                  asm, ".4h", ".4h",
9699              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9700                    (i32 vecshiftL16:$imm)))]> {
9701    bits<4> imm;
9702    let Inst{19-16} = imm;
9703  }
9704
9705  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9706                                  V128, V128, vecshiftL16,
9707                                  asm, ".8h", ".8h",
9708            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9709                  (i32 vecshiftL16:$imm)))]> {
9710    bits<4> imm;
9711    let Inst{19-16} = imm;
9712  }
9713
9714  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9715                                  V64, V64, vecshiftL32,
9716                                  asm, ".2s", ".2s",
9717              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9718                    (i32 vecshiftL32:$imm)))]> {
9719    bits<5> imm;
9720    let Inst{20-16} = imm;
9721  }
9722
9723  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9724                                  V128, V128, vecshiftL32,
9725                                  asm, ".4s", ".4s",
9726            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9727                  (i32 vecshiftL32:$imm)))]> {
9728    bits<5> imm;
9729    let Inst{20-16} = imm;
9730  }
9731
9732  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9733                                  V128, V128, vecshiftL64,
9734                                  asm, ".2d", ".2d",
9735            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9736                  (i32 vecshiftL64:$imm)))]> {
9737    bits<6> imm;
9738    let Inst{21-16} = imm;
9739  }
9740}
9741
9742multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9743                                SDPatternOperator OpNode> {
9744  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9745                                  V64, V64, vecshiftR8,
9746                                  asm, ".8b", ".8b",
9747                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9748                       (i32 vecshiftR8:$imm)))]> {
9749    bits<3> imm;
9750    let Inst{18-16} = imm;
9751  }
9752
9753  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9754                                  V128, V128, vecshiftR8,
9755                                  asm, ".16b", ".16b",
9756             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9757                   (i32 vecshiftR8:$imm)))]> {
9758    bits<3> imm;
9759    let Inst{18-16} = imm;
9760  }
9761
9762  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9763                                  V64, V64, vecshiftR16,
9764                                  asm, ".4h", ".4h",
9765              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9766                    (i32 vecshiftR16:$imm)))]> {
9767    bits<4> imm;
9768    let Inst{19-16} = imm;
9769  }
9770
9771  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9772                                  V128, V128, vecshiftR16,
9773                                  asm, ".8h", ".8h",
9774            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9775                  (i32 vecshiftR16:$imm)))]> {
9776    bits<4> imm;
9777    let Inst{19-16} = imm;
9778  }
9779
9780  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9781                                  V64, V64, vecshiftR32,
9782                                  asm, ".2s", ".2s",
9783              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9784                    (i32 vecshiftR32:$imm)))]> {
9785    bits<5> imm;
9786    let Inst{20-16} = imm;
9787  }
9788
9789  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9790                                  V128, V128, vecshiftR32,
9791                                  asm, ".4s", ".4s",
9792            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9793                  (i32 vecshiftR32:$imm)))]> {
9794    bits<5> imm;
9795    let Inst{20-16} = imm;
9796  }
9797
9798  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9799                                  V128, V128, vecshiftR64,
9800                                  asm, ".2d", ".2d",
9801            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9802                  (i32 vecshiftR64:$imm)))]> {
9803    bits<6> imm;
9804    let Inst{21-16} = imm;
9805  }
9806}
9807
9808let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9809multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9810                                    SDPatternOperator OpNode = null_frag> {
9811  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9812                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9813                 [(set (v8i8 V64:$dst),
9814                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9815                           (i32 vecshiftR8:$imm)))]> {
9816    bits<3> imm;
9817    let Inst{18-16} = imm;
9818  }
9819
9820  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9821                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9822             [(set (v16i8 V128:$dst),
9823               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9824                       (i32 vecshiftR8:$imm)))]> {
9825    bits<3> imm;
9826    let Inst{18-16} = imm;
9827  }
9828
9829  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9830                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9831              [(set (v4i16 V64:$dst),
9832                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9833                        (i32 vecshiftR16:$imm)))]> {
9834    bits<4> imm;
9835    let Inst{19-16} = imm;
9836  }
9837
9838  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9839                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9840            [(set (v8i16 V128:$dst),
9841              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9842                      (i32 vecshiftR16:$imm)))]> {
9843    bits<4> imm;
9844    let Inst{19-16} = imm;
9845  }
9846
9847  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9848                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9849              [(set (v2i32 V64:$dst),
9850                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9851                        (i32 vecshiftR32:$imm)))]> {
9852    bits<5> imm;
9853    let Inst{20-16} = imm;
9854  }
9855
9856  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9857                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9858            [(set (v4i32 V128:$dst),
9859              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9860                      (i32 vecshiftR32:$imm)))]> {
9861    bits<5> imm;
9862    let Inst{20-16} = imm;
9863  }
9864
9865  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9866                                  V128, V128, vecshiftR64,
9867                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9868              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9869                      (i32 vecshiftR64:$imm)))]> {
9870    bits<6> imm;
9871    let Inst{21-16} = imm;
9872  }
9873}
9874
9875multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9876                                    SDPatternOperator OpNode = null_frag> {
9877  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9878                                  V64, V64, vecshiftL8,
9879                                  asm, ".8b", ".8b",
9880                    [(set (v8i8 V64:$dst),
9881                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9882                                  (i32 vecshiftL8:$imm)))]> {
9883    bits<3> imm;
9884    let Inst{18-16} = imm;
9885  }
9886
9887  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9888                                  V128, V128, vecshiftL8,
9889                                  asm, ".16b", ".16b",
9890                    [(set (v16i8 V128:$dst),
9891                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9892                                  (i32 vecshiftL8:$imm)))]> {
9893    bits<3> imm;
9894    let Inst{18-16} = imm;
9895  }
9896
9897  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9898                                  V64, V64, vecshiftL16,
9899                                  asm, ".4h", ".4h",
9900                    [(set (v4i16 V64:$dst),
9901                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9902                                   (i32 vecshiftL16:$imm)))]> {
9903    bits<4> imm;
9904    let Inst{19-16} = imm;
9905  }
9906
9907  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9908                                  V128, V128, vecshiftL16,
9909                                  asm, ".8h", ".8h",
9910                    [(set (v8i16 V128:$dst),
9911                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9912                                  (i32 vecshiftL16:$imm)))]> {
9913    bits<4> imm;
9914    let Inst{19-16} = imm;
9915  }
9916
9917  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9918                                  V64, V64, vecshiftL32,
9919                                  asm, ".2s", ".2s",
9920                    [(set (v2i32 V64:$dst),
9921                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9922                                  (i32 vecshiftL32:$imm)))]> {
9923    bits<5> imm;
9924    let Inst{20-16} = imm;
9925  }
9926
9927  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9928                                  V128, V128, vecshiftL32,
9929                                  asm, ".4s", ".4s",
9930                    [(set (v4i32 V128:$dst),
9931                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9932                                  (i32 vecshiftL32:$imm)))]> {
9933    bits<5> imm;
9934    let Inst{20-16} = imm;
9935  }
9936
9937  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9938                                  V128, V128, vecshiftL64,
9939                                  asm, ".2d", ".2d",
9940                    [(set (v2i64 V128:$dst),
9941                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9942                                  (i32 vecshiftL64:$imm)))]> {
9943    bits<6> imm;
9944    let Inst{21-16} = imm;
9945  }
9946}
9947
9948multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9949                                   SDPatternOperator OpNode> {
9950  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9951                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9952      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9953    bits<3> imm;
9954    let Inst{18-16} = imm;
9955  }
9956
9957  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9958                                  V128, V128, vecshiftL8,
9959                                  asm#"2", ".8h", ".16b",
9960      [(set (v8i16 V128:$Rd),
9961            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
9962    bits<3> imm;
9963    let Inst{18-16} = imm;
9964  }
9965
9966  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9967                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9968      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9969    bits<4> imm;
9970    let Inst{19-16} = imm;
9971  }
9972
9973  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9974                                  V128, V128, vecshiftL16,
9975                                  asm#"2", ".4s", ".8h",
9976      [(set (v4i32 V128:$Rd),
9977            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
9978
9979    bits<4> imm;
9980    let Inst{19-16} = imm;
9981  }
9982
9983  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9984                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9985      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9986    bits<5> imm;
9987    let Inst{20-16} = imm;
9988  }
9989
9990  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9991                                  V128, V128, vecshiftL32,
9992                                  asm#"2", ".2d", ".4s",
9993      [(set (v2i64 V128:$Rd),
9994            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
9995    bits<5> imm;
9996    let Inst{20-16} = imm;
9997  }
9998}
9999
10000
10001//---
10002// Vector load/store
10003//---
10004// SIMD ldX/stX no-index memory references don't allow the optional
10005// ", #0" constant and handle post-indexing explicitly, so we use
10006// a more specialized parse method for them. Otherwise, it's the same as
10007// the general GPR64sp handling.
10008
10009class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
10010                   string asm, dag oops, dag iops, list<dag> pattern>
10011  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
10012  bits<5> Vt;
10013  bits<5> Rn;
10014  let Inst{31} = 0;
10015  let Inst{30} = Q;
10016  let Inst{29-23} = 0b0011000;
10017  let Inst{22} = L;
10018  let Inst{21-16} = 0b000000;
10019  let Inst{15-12} = opcode;
10020  let Inst{11-10} = size;
10021  let Inst{9-5} = Rn;
10022  let Inst{4-0} = Vt;
10023}
10024
10025class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
10026                       string asm, dag oops, dag iops>
10027  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
10028  bits<5> Vt;
10029  bits<5> Rn;
10030  bits<5> Xm;
10031  let Inst{31} = 0;
10032  let Inst{30} = Q;
10033  let Inst{29-23} = 0b0011001;
10034  let Inst{22} = L;
10035  let Inst{21} = 0;
10036  let Inst{20-16} = Xm;
10037  let Inst{15-12} = opcode;
10038  let Inst{11-10} = size;
10039  let Inst{9-5} = Rn;
10040  let Inst{4-0} = Vt;
10041}
10042
10043// The immediate form of AdvSIMD post-indexed addressing is encoded with
10044// register post-index addressing from the zero register.
10045multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
10046                           int Offset, int Size> {
10047  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
10048  //      "ld1\t$Vt, [$Rn], #16"
10049  // may get mapped to
10050  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
10051  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10052                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10053                      GPR64sp:$Rn,
10054                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10055                      XZR), 1>;
10056
10057  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
10058  //      "ld1.8b\t$Vt, [$Rn], #16"
10059  // may get mapped to
10060  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
10061  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10062                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10063                      GPR64sp:$Rn,
10064                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10065                      XZR), 0>;
10066
10067  // E.g. "ld1.8b { v0, v1 }, [x1]"
10068  //      "ld1\t$Vt, [$Rn]"
10069  // may get mapped to
10070  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
10071  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10072                  (!cast<Instruction>(BaseName # Count # "v" # layout)
10073                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10074                      GPR64sp:$Rn), 0>;
10075
10076  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
10077  //      "ld1\t$Vt, [$Rn], $Xm"
10078  // may get mapped to
10079  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
10080  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10081                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10082                      GPR64sp:$Rn,
10083                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10084                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10085}
10086
10087multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
10088                       int Offset128, int Offset64, bits<4> opcode> {
10089  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10090    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
10091                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
10092                           (ins GPR64sp:$Rn), []>;
10093    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
10094                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
10095                           (ins GPR64sp:$Rn), []>;
10096    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
10097                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
10098                           (ins GPR64sp:$Rn), []>;
10099    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
10100                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
10101                           (ins GPR64sp:$Rn), []>;
10102    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
10103                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
10104                           (ins GPR64sp:$Rn), []>;
10105    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
10106                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
10107                           (ins GPR64sp:$Rn), []>;
10108    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
10109                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
10110                           (ins GPR64sp:$Rn), []>;
10111
10112
10113    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
10114                       (outs GPR64sp:$wback,
10115                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
10116                       (ins GPR64sp:$Rn,
10117                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10118    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
10119                       (outs GPR64sp:$wback,
10120                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
10121                       (ins GPR64sp:$Rn,
10122                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10123    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
10124                       (outs GPR64sp:$wback,
10125                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
10126                       (ins GPR64sp:$Rn,
10127                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10128    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
10129                       (outs GPR64sp:$wback,
10130                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
10131                       (ins GPR64sp:$Rn,
10132                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10133    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
10134                       (outs GPR64sp:$wback,
10135                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
10136                       (ins GPR64sp:$Rn,
10137                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10138    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
10139                       (outs GPR64sp:$wback,
10140                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
10141                       (ins GPR64sp:$Rn,
10142                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10143    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
10144                       (outs GPR64sp:$wback,
10145                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
10146                       (ins GPR64sp:$Rn,
10147                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10148  }
10149
10150  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10151  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10152  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10153  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10154  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10155  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10156  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10157}
10158
10159// Only ld1/st1 has a v1d version.
10160multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
10161                       int Offset128, int Offset64, bits<4> opcode> {
10162  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
10163    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
10164                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10165                                 GPR64sp:$Rn), []>;
10166    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
10167                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10168                                GPR64sp:$Rn), []>;
10169    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
10170                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10171                                GPR64sp:$Rn), []>;
10172    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
10173                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10174                                GPR64sp:$Rn), []>;
10175    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
10176                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10177                                GPR64sp:$Rn), []>;
10178    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
10179                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10180                                GPR64sp:$Rn), []>;
10181    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
10182                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10183                                GPR64sp:$Rn), []>;
10184
10185    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
10186                       (outs GPR64sp:$wback),
10187                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10188                            GPR64sp:$Rn,
10189                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10190    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
10191                       (outs GPR64sp:$wback),
10192                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10193                            GPR64sp:$Rn,
10194                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10195    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
10196                       (outs GPR64sp:$wback),
10197                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10198                            GPR64sp:$Rn,
10199                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10200    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
10201                       (outs GPR64sp:$wback),
10202                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10203                            GPR64sp:$Rn,
10204                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10205    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
10206                       (outs GPR64sp:$wback),
10207                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10208                            GPR64sp:$Rn,
10209                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10210    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
10211                       (outs GPR64sp:$wback),
10212                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10213                            GPR64sp:$Rn,
10214                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10215    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
10216                       (outs GPR64sp:$wback),
10217                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10218                            GPR64sp:$Rn,
10219                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10220  }
10221
10222  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10223  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10224  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10225  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10226  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10227  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10228  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10229}
10230
10231multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
10232                       int Offset128, int Offset64, bits<4> opcode>
10233  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10234
10235  // LD1 instructions have extra "1d" variants.
10236  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10237    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
10238                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10239                           (ins GPR64sp:$Rn), []>;
10240
10241    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10242                       (outs GPR64sp:$wback,
10243                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10244                       (ins GPR64sp:$Rn,
10245                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10246  }
10247
10248  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10249}
10250
10251multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10252                       int Offset128, int Offset64, bits<4> opcode>
10253  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10254
10255  // ST1 instructions have extra "1d" variants.
10256  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10257    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10258                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10259                                GPR64sp:$Rn), []>;
10260
10261    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10262                       (outs GPR64sp:$wback),
10263                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10264                            GPR64sp:$Rn,
10265                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10266  }
10267
10268  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10269}
10270
10271multiclass SIMDLd1Multiple<string asm> {
10272  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10273  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10274  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10275  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10276}
10277
10278multiclass SIMDSt1Multiple<string asm> {
10279  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10280  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10281  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10282  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10283}
10284
10285multiclass SIMDLd2Multiple<string asm> {
10286  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10287}
10288
10289multiclass SIMDSt2Multiple<string asm> {
10290  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10291}
10292
10293multiclass SIMDLd3Multiple<string asm> {
10294  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10295}
10296
10297multiclass SIMDSt3Multiple<string asm> {
10298  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10299}
10300
10301multiclass SIMDLd4Multiple<string asm> {
10302  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10303}
10304
10305multiclass SIMDSt4Multiple<string asm> {
10306  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10307}
10308
10309//---
10310// AdvSIMD Load/store single-element
10311//---
10312
10313class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10314                         string asm, string operands, string cst,
10315                         dag oops, dag iops, list<dag> pattern>
10316  : I<oops, iops, asm, operands, cst, pattern> {
10317  bits<5> Vt;
10318  bits<5> Rn;
10319  let Inst{31} = 0;
10320  let Inst{29-24} = 0b001101;
10321  let Inst{22} = L;
10322  let Inst{21} = R;
10323  let Inst{15-13} = opcode;
10324  let Inst{9-5} = Rn;
10325  let Inst{4-0} = Vt;
10326}
10327
10328class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10329                         string asm, string operands, string cst,
10330                         dag oops, dag iops, list<dag> pattern>
10331  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10332  bits<5> Vt;
10333  bits<5> Rn;
10334  let Inst{31} = 0;
10335  let Inst{29-24} = 0b001101;
10336  let Inst{22} = L;
10337  let Inst{21} = R;
10338  let Inst{15-13} = opcode;
10339  let Inst{9-5} = Rn;
10340  let Inst{4-0} = Vt;
10341}
10342
10343
10344let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10345class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10346                  DAGOperand listtype>
10347  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10348                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10349                       []> {
10350  let Inst{30} = Q;
10351  let Inst{23} = 0;
10352  let Inst{20-16} = 0b00000;
10353  let Inst{12} = S;
10354  let Inst{11-10} = size;
10355}
10356let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10357class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10358                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10359  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10360                       "$Rn = $wback",
10361                       (outs GPR64sp:$wback, listtype:$Vt),
10362                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10363  bits<5> Xm;
10364  let Inst{30} = Q;
10365  let Inst{23} = 1;
10366  let Inst{20-16} = Xm;
10367  let Inst{12} = S;
10368  let Inst{11-10} = size;
10369}
10370
10371multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10372                          int Offset, int Size> {
10373  // E.g. "ld1r { v0.8b }, [x1], #1"
10374  //      "ld1r.8b\t$Vt, [$Rn], #1"
10375  // may get mapped to
10376  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10377  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10378                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10379                      GPR64sp:$Rn,
10380                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10381                      XZR), 1>;
10382
10383  // E.g. "ld1r.8b { v0 }, [x1], #1"
10384  //      "ld1r.8b\t$Vt, [$Rn], #1"
10385  // may get mapped to
10386  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10387  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10388                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10389                      GPR64sp:$Rn,
10390                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10391                      XZR), 0>;
10392
10393  // E.g. "ld1r.8b { v0 }, [x1]"
10394  //      "ld1r.8b\t$Vt, [$Rn]"
10395  // may get mapped to
10396  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10397  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10398                  (!cast<Instruction>(BaseName # "v" # layout)
10399                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10400                      GPR64sp:$Rn), 0>;
10401
10402  // E.g. "ld1r.8b { v0 }, [x1], x2"
10403  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10404  // may get mapped to
10405  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10406  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10407                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10408                      GPR64sp:$Rn,
10409                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10410                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10411}
10412
10413multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10414  int Offset1, int Offset2, int Offset4, int Offset8> {
10415  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10416                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10417  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10418                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10419  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10420                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10421  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10422                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10423  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10424                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10425  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10426                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10427  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10428                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10429  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10430                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10431
10432  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10433                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10434                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10435  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10436                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10437                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10438  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10439                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10440                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10441  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10442                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10443                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10444  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10445                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10446                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10447  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10448                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10449                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10450  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10451                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10452                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10453  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10454                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10455                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10456
10457  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10458  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10459  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10460  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10461  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10462  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10463  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10464  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10465}
10466
10467class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10468                      dag oops, dag iops, list<dag> pattern>
10469  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10470                       pattern> {
10471  // idx encoded in Q:S:size fields.
10472  bits<4> idx;
10473  let Inst{30} = idx{3};
10474  let Inst{23} = 0;
10475  let Inst{20-16} = 0b00000;
10476  let Inst{12} = idx{2};
10477  let Inst{11-10} = idx{1-0};
10478}
10479class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10480                      dag oops, dag iops, list<dag> pattern>
10481  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10482                           oops, iops, pattern> {
10483  // idx encoded in Q:S:size fields.
10484  bits<4> idx;
10485  let Inst{30} = idx{3};
10486  let Inst{23} = 0;
10487  let Inst{20-16} = 0b00000;
10488  let Inst{12} = idx{2};
10489  let Inst{11-10} = idx{1-0};
10490}
10491class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10492                          dag oops, dag iops>
10493  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10494                       "$Rn = $wback", oops, iops, []> {
10495  // idx encoded in Q:S:size fields.
10496  bits<4> idx;
10497  bits<5> Xm;
10498  let Inst{30} = idx{3};
10499  let Inst{23} = 1;
10500  let Inst{20-16} = Xm;
10501  let Inst{12} = idx{2};
10502  let Inst{11-10} = idx{1-0};
10503}
10504class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10505                          dag oops, dag iops>
10506  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10507                           "$Rn = $wback", oops, iops, []> {
10508  // idx encoded in Q:S:size fields.
10509  bits<4> idx;
10510  bits<5> Xm;
10511  let Inst{30} = idx{3};
10512  let Inst{23} = 1;
10513  let Inst{20-16} = Xm;
10514  let Inst{12} = idx{2};
10515  let Inst{11-10} = idx{1-0};
10516}
10517
10518class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10519                      dag oops, dag iops, list<dag> pattern>
10520  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10521                       pattern> {
10522  // idx encoded in Q:S:size<1> fields.
10523  bits<3> idx;
10524  let Inst{30} = idx{2};
10525  let Inst{23} = 0;
10526  let Inst{20-16} = 0b00000;
10527  let Inst{12} = idx{1};
10528  let Inst{11} = idx{0};
10529  let Inst{10} = size;
10530}
10531class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10532                      dag oops, dag iops, list<dag> pattern>
10533  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10534                           oops, iops, pattern> {
10535  // idx encoded in Q:S:size<1> fields.
10536  bits<3> idx;
10537  let Inst{30} = idx{2};
10538  let Inst{23} = 0;
10539  let Inst{20-16} = 0b00000;
10540  let Inst{12} = idx{1};
10541  let Inst{11} = idx{0};
10542  let Inst{10} = size;
10543}
10544
10545class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10546                          dag oops, dag iops>
10547  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10548                       "$Rn = $wback", oops, iops, []> {
10549  // idx encoded in Q:S:size<1> fields.
10550  bits<3> idx;
10551  bits<5> Xm;
10552  let Inst{30} = idx{2};
10553  let Inst{23} = 1;
10554  let Inst{20-16} = Xm;
10555  let Inst{12} = idx{1};
10556  let Inst{11} = idx{0};
10557  let Inst{10} = size;
10558}
10559class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10560                          dag oops, dag iops>
10561  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10562                           "$Rn = $wback", oops, iops, []> {
10563  // idx encoded in Q:S:size<1> fields.
10564  bits<3> idx;
10565  bits<5> Xm;
10566  let Inst{30} = idx{2};
10567  let Inst{23} = 1;
10568  let Inst{20-16} = Xm;
10569  let Inst{12} = idx{1};
10570  let Inst{11} = idx{0};
10571  let Inst{10} = size;
10572}
10573class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10574                      dag oops, dag iops, list<dag> pattern>
10575  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10576                       pattern> {
10577  // idx encoded in Q:S fields.
10578  bits<2> idx;
10579  let Inst{30} = idx{1};
10580  let Inst{23} = 0;
10581  let Inst{20-16} = 0b00000;
10582  let Inst{12} = idx{0};
10583  let Inst{11-10} = size;
10584}
10585class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10586                      dag oops, dag iops, list<dag> pattern>
10587  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10588                           oops, iops, pattern> {
10589  // idx encoded in Q:S fields.
10590  bits<2> idx;
10591  let Inst{30} = idx{1};
10592  let Inst{23} = 0;
10593  let Inst{20-16} = 0b00000;
10594  let Inst{12} = idx{0};
10595  let Inst{11-10} = size;
10596}
10597class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10598                          string asm, dag oops, dag iops>
10599  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10600                       "$Rn = $wback", oops, iops, []> {
10601  // idx encoded in Q:S fields.
10602  bits<2> idx;
10603  bits<5> Xm;
10604  let Inst{30} = idx{1};
10605  let Inst{23} = 1;
10606  let Inst{20-16} = Xm;
10607  let Inst{12} = idx{0};
10608  let Inst{11-10} = size;
10609}
10610class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10611                          string asm, dag oops, dag iops>
10612  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10613                           "$Rn = $wback", oops, iops, []> {
10614  // idx encoded in Q:S fields.
10615  bits<2> idx;
10616  bits<5> Xm;
10617  let Inst{30} = idx{1};
10618  let Inst{23} = 1;
10619  let Inst{20-16} = Xm;
10620  let Inst{12} = idx{0};
10621  let Inst{11-10} = size;
10622}
10623class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10624                      dag oops, dag iops, list<dag> pattern>
10625  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10626                       pattern> {
10627  // idx encoded in Q field.
10628  bits<1> idx;
10629  let Inst{30} = idx;
10630  let Inst{23} = 0;
10631  let Inst{20-16} = 0b00000;
10632  let Inst{12} = 0;
10633  let Inst{11-10} = size;
10634}
10635class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10636                      dag oops, dag iops, list<dag> pattern>
10637  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10638                           oops, iops, pattern> {
10639  // idx encoded in Q field.
10640  bits<1> idx;
10641  let Inst{30} = idx;
10642  let Inst{23} = 0;
10643  let Inst{20-16} = 0b00000;
10644  let Inst{12} = 0;
10645  let Inst{11-10} = size;
10646}
10647class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10648                          string asm, dag oops, dag iops>
10649  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10650                       "$Rn = $wback", oops, iops, []> {
10651  // idx encoded in Q field.
10652  bits<1> idx;
10653  bits<5> Xm;
10654  let Inst{30} = idx;
10655  let Inst{23} = 1;
10656  let Inst{20-16} = Xm;
10657  let Inst{12} = 0;
10658  let Inst{11-10} = size;
10659}
10660class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10661                          string asm, dag oops, dag iops>
10662  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10663                           "$Rn = $wback", oops, iops, []> {
10664  // idx encoded in Q field.
10665  bits<1> idx;
10666  bits<5> Xm;
10667  let Inst{30} = idx;
10668  let Inst{23} = 1;
10669  let Inst{20-16} = Xm;
10670  let Inst{12} = 0;
10671  let Inst{11-10} = size;
10672}
10673
10674let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10675multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10676                         RegisterOperand listtype,
10677                         RegisterOperand GPR64pi> {
10678  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10679                           (outs listtype:$dst),
10680                           (ins listtype:$Vt, VectorIndexB:$idx,
10681                                GPR64sp:$Rn), []>;
10682
10683  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10684                            (outs GPR64sp:$wback, listtype:$dst),
10685                            (ins listtype:$Vt, VectorIndexB:$idx,
10686                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10687}
10688let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10689multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10690                         RegisterOperand listtype,
10691                         RegisterOperand GPR64pi> {
10692  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10693                            (outs listtype:$dst),
10694                            (ins listtype:$Vt, VectorIndexH:$idx,
10695                                 GPR64sp:$Rn), []>;
10696
10697  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10698                            (outs GPR64sp:$wback, listtype:$dst),
10699                            (ins listtype:$Vt, VectorIndexH:$idx,
10700                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10701}
10702let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10703multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10704                         RegisterOperand listtype,
10705                         RegisterOperand GPR64pi> {
10706  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10707                            (outs listtype:$dst),
10708                            (ins listtype:$Vt, VectorIndexS:$idx,
10709                                 GPR64sp:$Rn), []>;
10710
10711  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10712                            (outs GPR64sp:$wback, listtype:$dst),
10713                            (ins listtype:$Vt, VectorIndexS:$idx,
10714                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10715}
10716let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10717multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10718                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10719  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10720                            (outs listtype:$dst),
10721                            (ins listtype:$Vt, VectorIndexD:$idx,
10722                                 GPR64sp:$Rn), []>;
10723
10724  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10725                            (outs GPR64sp:$wback, listtype:$dst),
10726                            (ins listtype:$Vt, VectorIndexD:$idx,
10727                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10728}
10729let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10730multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10731                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10732  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10733                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10734                                        GPR64sp:$Rn), []>;
10735
10736  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10737                                    (outs GPR64sp:$wback),
10738                                    (ins listtype:$Vt, VectorIndexB:$idx,
10739                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10740}
10741let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10742multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10743                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10744  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10745                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10746                                         GPR64sp:$Rn), []>;
10747
10748  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10749                            (outs GPR64sp:$wback),
10750                            (ins listtype:$Vt, VectorIndexH:$idx,
10751                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10752}
10753let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10754multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10755                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10756  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10757                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10758                                         GPR64sp:$Rn), []>;
10759
10760  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10761                            (outs GPR64sp:$wback),
10762                            (ins listtype:$Vt, VectorIndexS:$idx,
10763                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10764}
10765let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10766multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10767                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10768  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10769                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10770                                         GPR64sp:$Rn), []>;
10771
10772  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10773                            (outs GPR64sp:$wback),
10774                            (ins listtype:$Vt, VectorIndexD:$idx,
10775                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10776}
10777
10778multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10779                                 string Count, int Offset, Operand idxtype> {
10780  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10781  //      "ld1\t$Vt, [$Rn], #1"
10782  // may get mapped to
10783  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10784  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10785                  (!cast<Instruction>(NAME # Type  # "_POST")
10786                      GPR64sp:$Rn,
10787                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10788                      idxtype:$idx, XZR), 1>;
10789
10790  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10791  //      "ld1.8b\t$Vt, [$Rn], #1"
10792  // may get mapped to
10793  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10794  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10795                  (!cast<Instruction>(NAME # Type # "_POST")
10796                      GPR64sp:$Rn,
10797                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10798                      idxtype:$idx, XZR), 0>;
10799
10800  // E.g. "ld1.8b { v0 }[0], [x1]"
10801  //      "ld1.8b\t$Vt, [$Rn]"
10802  // may get mapped to
10803  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10804  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10805                      (!cast<Instruction>(NAME # Type)
10806                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10807                         idxtype:$idx, GPR64sp:$Rn), 0>;
10808
10809  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10810  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10811  // may get mapped to
10812  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10813  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10814                      (!cast<Instruction>(NAME # Type # "_POST")
10815                         GPR64sp:$Rn,
10816                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10817                         idxtype:$idx,
10818                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10819}
10820
10821multiclass SIMDLdSt1SingleAliases<string asm> {
10822  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10823  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10824  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10825  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10826}
10827
10828multiclass SIMDLdSt2SingleAliases<string asm> {
10829  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10830  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10831  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10832  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10833}
10834
10835multiclass SIMDLdSt3SingleAliases<string asm> {
10836  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10837  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10838  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10839  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10840}
10841
10842multiclass SIMDLdSt4SingleAliases<string asm> {
10843  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10844  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10845  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10846  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10847}
10848} // end of 'let Predicates = [HasNEON]'
10849
10850//----------------------------------------------------------------------------
10851// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10852//----------------------------------------------------------------------------
10853
10854let Predicates = [HasNEON, HasRDM] in {
10855
10856class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10857                                    RegisterOperand regtype, string asm,
10858                                    string kind, list<dag> pattern>
10859  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10860                                pattern> {
10861}
10862multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10863                                             SDPatternOperator op> {
10864  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10865    [(set (v4i16 V64:$dst),
10866          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
10867  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10868    [(set (v8i16 V128:$dst),
10869          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
10870  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10871    [(set (v2i32 V64:$dst),
10872          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
10873  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10874    [(set (v4i32 V128:$dst),
10875          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
10876}
10877
10878multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10879                                     SDPatternOperator op> {
10880  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10881                                          V64, V64, V128_lo, VectorIndexH,
10882                                          asm, ".4h", ".4h", ".4h", ".h",
10883    [(set (v4i16 V64:$dst),
10884          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10885                     (dup_v8i16 (v8i16 V128_lo:$Rm),
10886                                 VectorIndexH:$idx))))]> {
10887    bits<3> idx;
10888    let Inst{11} = idx{2};
10889    let Inst{21} = idx{1};
10890    let Inst{20} = idx{0};
10891  }
10892
10893  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10894                                          V128, V128, V128_lo, VectorIndexH,
10895                                          asm, ".8h", ".8h", ".8h", ".h",
10896    [(set (v8i16 V128:$dst),
10897          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10898                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10899                                              VectorIndexH:$idx)))))]> {
10900    bits<3> idx;
10901    let Inst{11} = idx{2};
10902    let Inst{21} = idx{1};
10903    let Inst{20} = idx{0};
10904  }
10905
10906  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10907                                          V64, V64, V128, VectorIndexS,
10908                                          asm, ".2s", ".2s", ".2s", ".s",
10909    [(set (v2i32 V64:$dst),
10910          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10911                     (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
10912    bits<2> idx;
10913    let Inst{11} = idx{1};
10914    let Inst{21} = idx{0};
10915  }
10916
10917  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10918                                          V128, V128, V128, VectorIndexS,
10919                                          asm, ".4s", ".4s", ".4s", ".s",
10920    [(set (v4i32 V128:$dst),
10921          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10922                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10923                                              VectorIndexS:$idx)))))]> {
10924    bits<2> idx;
10925    let Inst{11} = idx{1};
10926    let Inst{21} = idx{0};
10927  }
10928
10929  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10930                                          FPR16Op, FPR16Op, V128_lo,
10931                                          VectorIndexH, asm, ".h", "", "", ".h",
10932                                          []> {
10933    bits<3> idx;
10934    let Inst{11} = idx{2};
10935    let Inst{21} = idx{1};
10936    let Inst{20} = idx{0};
10937  }
10938
10939  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10940                                          FPR32Op, FPR32Op, V128, VectorIndexS,
10941                                          asm, ".s", "", "", ".s",
10942    [(set (i32 FPR32Op:$dst),
10943          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
10944                   (i32 (vector_extract (v4i32 V128:$Rm),
10945                                        VectorIndexS:$idx)))))]> {
10946    bits<2> idx;
10947    let Inst{11} = idx{1};
10948    let Inst{21} = idx{0};
10949  }
10950}
10951} // let Predicates = [HasNeon, HasRDM]
10952
10953//----------------------------------------------------------------------------
10954// ARMv8.3 Complex ADD/MLA instructions
10955//----------------------------------------------------------------------------
10956
10957class ComplexRotationOperand<int Angle, int Remainder, string Type>
10958  : AsmOperandClass {
10959  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10960  let DiagnosticType = "InvalidComplexRotation" # Type;
10961  let Name = "ComplexRotation" # Type;
10962}
10963def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10964                                                  SDNodeXForm<imm, [{
10965  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10966}]>> {
10967  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10968  let PrintMethod = "printComplexRotationOp<90, 0>";
10969}
10970def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10971                                                  SDNodeXForm<imm, [{
10972  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10973}]>> {
10974  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10975  let PrintMethod = "printComplexRotationOp<180, 90>";
10976}
10977let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
10978class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10979                                     RegisterOperand regtype, Operand rottype,
10980                                     string asm, string kind, list<dag> pattern>
10981  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10982      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10983      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10984    Sched<[!if(Q, WriteVq, WriteVd)]> {
10985  bits<5> Rd;
10986  bits<5> Rn;
10987  bits<5> Rm;
10988  bits<1> rot;
10989  let Inst{31}    = 0;
10990  let Inst{30}    = Q;
10991  let Inst{29}    = U;
10992  let Inst{28-24} = 0b01110;
10993  let Inst{23-22} = size;
10994  let Inst{21}    = 0;
10995  let Inst{20-16} = Rm;
10996  let Inst{15-13} = opcode;
10997  // Non-tied version (FCADD) only has one rotation bit
10998  let Inst{12}    = rot;
10999  let Inst{11}    = 0;
11000  let Inst{10}    = 1;
11001  let Inst{9-5}   = Rn;
11002  let Inst{4-0}   = Rd;
11003}
11004
11005//8.3 CompNum - Floating-point complex number support
11006multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
11007                                          string asm, SDPatternOperator OpNode>{
11008  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11009  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
11010              asm, ".4h",
11011              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11012                                              (v4f16 V64:$Rn),
11013                                              (v4f16 V64:$Rm),
11014                                              (i32 rottype:$rot)))]>;
11015
11016  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
11017              asm, ".8h",
11018              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11019                                               (v8f16 V128:$Rn),
11020                                               (v8f16 V128:$Rm),
11021                                               (i32 rottype:$rot)))]>;
11022  }
11023
11024  let Predicates = [HasComplxNum, HasNEON] in {
11025  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
11026              asm, ".2s",
11027              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11028                                              (v2f32 V64:$Rn),
11029                                              (v2f32 V64:$Rm),
11030                                              (i32 rottype:$rot)))]>;
11031
11032  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
11033              asm, ".4s",
11034              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11035                                               (v4f32 V128:$Rn),
11036                                               (v4f32 V128:$Rm),
11037                                               (i32 rottype:$rot)))]>;
11038
11039  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
11040              asm, ".2d",
11041              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11042                                               (v2f64 V128:$Rn),
11043                                               (v2f64 V128:$Rm),
11044                                               (i32 rottype:$rot)))]>;
11045  }
11046}
11047
11048let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11049class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
11050                                         bits<3> opcode,
11051                                         RegisterOperand regtype,
11052                                         Operand rottype, string asm,
11053                                         string kind, list<dag> pattern>
11054  : I<(outs regtype:$dst),
11055      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11056      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11057      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
11058    Sched<[!if(Q, WriteVq, WriteVd)]> {
11059  bits<5> Rd;
11060  bits<5> Rn;
11061  bits<5> Rm;
11062  bits<2> rot;
11063  let Inst{31}    = 0;
11064  let Inst{30}    = Q;
11065  let Inst{29}    = U;
11066  let Inst{28-24} = 0b01110;
11067  let Inst{23-22} = size;
11068  let Inst{21}    = 0;
11069  let Inst{20-16} = Rm;
11070  let Inst{15-13} = opcode;
11071  let Inst{12-11} = rot;
11072  let Inst{10}    = 1;
11073  let Inst{9-5}   = Rn;
11074  let Inst{4-0}   = Rd;
11075}
11076
11077multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
11078                                             Operand rottype, string asm,
11079                                             SDPatternOperator OpNode> {
11080  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11081  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
11082              rottype, asm, ".4h",
11083              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11084                                              (v4f16 V64:$Rn),
11085                                              (v4f16 V64:$Rm),
11086                                              (i32 rottype:$rot)))]>;
11087
11088  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
11089              rottype, asm, ".8h",
11090              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11091                                               (v8f16 V128:$Rn),
11092                                               (v8f16 V128:$Rm),
11093                                               (i32 rottype:$rot)))]>;
11094  }
11095
11096  let Predicates = [HasComplxNum, HasNEON] in {
11097  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
11098              rottype, asm, ".2s",
11099              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11100                                              (v2f32 V64:$Rn),
11101                                              (v2f32 V64:$Rm),
11102                                              (i32 rottype:$rot)))]>;
11103
11104  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
11105              rottype, asm, ".4s",
11106              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11107                                               (v4f32 V128:$Rn),
11108                                               (v4f32 V128:$Rm),
11109                                               (i32 rottype:$rot)))]>;
11110
11111  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
11112              rottype, asm, ".2d",
11113              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11114                                               (v2f64 V128:$Rn),
11115                                               (v2f64 V128:$Rm),
11116                                               (i32 rottype:$rot)))]>;
11117  }
11118}
11119
11120let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11121class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
11122                                 bit opc1, bit opc2, RegisterOperand dst_reg,
11123                                 RegisterOperand lhs_reg,
11124                                 RegisterOperand rhs_reg, Operand vec_idx,
11125                                 Operand rottype, string asm, string apple_kind,
11126                                 string dst_kind, string lhs_kind,
11127                                 string rhs_kind, list<dag> pattern>
11128  : I<(outs dst_reg:$dst),
11129      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
11130      asm,
11131      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
11132      "$idx, $rot" # "|" # apple_kind #
11133      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
11134    Sched<[!if(Q, WriteVq, WriteVd)]> {
11135  bits<5> Rd;
11136  bits<5> Rn;
11137  bits<5> Rm;
11138  bits<2> rot;
11139
11140  let Inst{31}    = 0;
11141  let Inst{30}    = Q;
11142  let Inst{29}    = U;
11143  let Inst{28}    = Scalar;
11144  let Inst{27-24} = 0b1111;
11145  let Inst{23-22} = size;
11146  // Bit 21 must be set by the derived class.
11147  let Inst{20-16} = Rm;
11148  let Inst{15}    = opc1;
11149  let Inst{14-13} = rot;
11150  let Inst{12}    = opc2;
11151  // Bit 11 must be set by the derived class.
11152  let Inst{10}    = 0;
11153  let Inst{9-5}   = Rn;
11154  let Inst{4-0}   = Rd;
11155}
11156
11157// The complex instructions index by pairs of elements, so the VectorIndexes
11158// don't match the lane types, and the index bits are different to the other
11159// classes.
11160multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
11161                                     string asm> {
11162  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11163  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
11164                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
11165                      ".4h", ".h", []> {
11166    bits<1> idx;
11167    let Inst{11} = 0;
11168    let Inst{21} = idx{0};
11169  }
11170
11171  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
11172                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
11173                      ".8h", ".8h", ".h", []> {
11174    bits<2> idx;
11175    let Inst{11} = idx{1};
11176    let Inst{21} = idx{0};
11177  }
11178  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
11179
11180  let Predicates = [HasComplxNum, HasNEON] in {
11181  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
11182                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
11183                      ".4s", ".4s", ".s", []> {
11184    bits<1> idx;
11185    let Inst{11} = idx{0};
11186    let Inst{21} = 0;
11187  }
11188  } // Predicates = [HasComplxNum, HasNEON]
11189}
11190
11191//----------------------------------------------------------------------------
11192// Crypto extensions
11193//----------------------------------------------------------------------------
11194
11195let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11196class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
11197              list<dag> pat>
11198  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
11199    Sched<[WriteVq]>{
11200  bits<5> Rd;
11201  bits<5> Rn;
11202  let Inst{31-16} = 0b0100111000101000;
11203  let Inst{15-12} = opc;
11204  let Inst{11-10} = 0b10;
11205  let Inst{9-5}   = Rn;
11206  let Inst{4-0}   = Rd;
11207}
11208
11209class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
11210  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
11211            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
11212
11213class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
11214  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
11215            "$Rd = $dst",
11216            [(set (v16i8 V128:$dst),
11217                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
11218
11219let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11220class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
11221                     dag oops, dag iops, list<dag> pat>
11222  : I<oops, iops, asm,
11223      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
11224      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
11225    Sched<[WriteVq]>{
11226  bits<5> Rd;
11227  bits<5> Rn;
11228  bits<5> Rm;
11229  let Inst{31-21} = 0b01011110000;
11230  let Inst{20-16} = Rm;
11231  let Inst{15}    = 0;
11232  let Inst{14-12} = opc;
11233  let Inst{11-10} = 0b00;
11234  let Inst{9-5}   = Rn;
11235  let Inst{4-0}   = Rd;
11236}
11237
11238class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11239  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11240                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11241                   [(set (v4i32 FPR128:$dst),
11242                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11243                                 (v4i32 V128:$Rm)))]>;
11244
11245class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11246  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11247                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11248                   [(set (v4i32 V128:$dst),
11249                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11250                                 (v4i32 V128:$Rm)))]>;
11251
11252class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11253  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11254                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11255                   [(set (v4i32 FPR128:$dst),
11256                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11257                                 (v4i32 V128:$Rm)))]>;
11258
11259let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11260class SHA2OpInst<bits<4> opc, string asm, string kind,
11261                 string cstr, dag oops, dag iops,
11262                 list<dag> pat>
11263  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11264                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11265    Sched<[WriteVq]>{
11266  bits<5> Rd;
11267  bits<5> Rn;
11268  let Inst{31-16} = 0b0101111000101000;
11269  let Inst{15-12} = opc;
11270  let Inst{11-10} = 0b10;
11271  let Inst{9-5}   = Rn;
11272  let Inst{4-0}   = Rd;
11273}
11274
11275class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11276  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11277               (ins V128:$Rd, V128:$Rn),
11278               [(set (v4i32 V128:$dst),
11279                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11280
11281class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11282  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11283               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11284
11285// Armv8.2-A Crypto extensions
11286class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11287                    list<dag> pattern>
11288  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11289  bits<5> Vd;
11290  bits<5> Vn;
11291  let Inst{31-25} = 0b1100111;
11292  let Inst{9-5}   = Vn;
11293  let Inst{4-0}   = Vd;
11294}
11295
11296class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11297  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11298                  "$Vd = $Vdst", []> {
11299  let Inst{31-25} = 0b1100111;
11300  let Inst{24-21} = 0b0110;
11301  let Inst{20-15} = 0b000001;
11302  let Inst{14}    = op0;
11303  let Inst{13-12} = 0b00;
11304  let Inst{11-10} = op1;
11305}
11306class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11307  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11308class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11309  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11310
11311class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11312                string asmops, string cst>
11313  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11314  bits<5> Vm;
11315  let Inst{24-21} = 0b0011;
11316  let Inst{20-16} = Vm;
11317  let Inst{15}    = 0b1;
11318  let Inst{14}    = op0;
11319  let Inst{13-12} = 0b00;
11320  let Inst{11-10} = op1;
11321}
11322class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11323  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11324              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11325class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11326  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11327              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11328class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11329  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11330              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11331class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11332  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11333              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11334class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11335  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11336              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11337
11338class CryptoRRRR<bits<2>op0, string asm, string asmops>
11339  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11340                  asmops, "", []> {
11341  bits<5> Vm;
11342  bits<5> Va;
11343  let Inst{24-23} = 0b00;
11344  let Inst{22-21} = op0;
11345  let Inst{20-16} = Vm;
11346  let Inst{15}    = 0b0;
11347  let Inst{14-10} = Va;
11348}
11349class CryptoRRRR_16B<bits<2>op0, string asm>
11350 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11351                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11352}
11353class CryptoRRRR_4S<bits<2>op0, string asm>
11354 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11355                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11356}
11357
11358class CryptoRRRi6<string asm>
11359  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11360                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11361                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11362  bits<6> imm;
11363  bits<5> Vm;
11364  let Inst{24-21} = 0b0100;
11365  let Inst{20-16} = Vm;
11366  let Inst{15-10} = imm;
11367  let Inst{9-5}   = Vn;
11368  let Inst{4-0}   = Vd;
11369}
11370
11371class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11372  : BaseCryptoV82<(outs V128:$Vdst),
11373                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11374                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11375                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11376  bits<2> imm;
11377  bits<5> Vm;
11378  let Inst{24-21} = 0b0010;
11379  let Inst{20-16} = Vm;
11380  let Inst{15}    = 0b1;
11381  let Inst{14}    = op0;
11382  let Inst{13-12} = imm;
11383  let Inst{11-10} = op1;
11384}
11385
11386//----------------------------------------------------------------------------
11387// v8.1 atomic instructions extension:
11388// * CAS
11389// * CASP
11390// * SWP
11391// * LDOPregister<OP>, and aliases STOPregister<OP>
11392
11393// Instruction encodings:
11394//
11395//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11396// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11397// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11398// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11399// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11400// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11401
11402// Instruction syntax:
11403//
11404// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11405// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11406// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11407// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11408// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11409// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11410// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11411// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11412// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11413// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11414
11415let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11416class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11417                      string cstr, list<dag> pattern>
11418      : I<oops, iops, asm, operands, cstr, pattern> {
11419  bits<2> Sz;
11420  bit NP;
11421  bit Acq;
11422  bit Rel;
11423  bits<5> Rs;
11424  bits<5> Rn;
11425  bits<5> Rt;
11426  let Inst{31-30} = Sz;
11427  let Inst{29-24} = 0b001000;
11428  let Inst{23} = NP;
11429  let Inst{22} = Acq;
11430  let Inst{21} = 0b1;
11431  let Inst{20-16} = Rs;
11432  let Inst{15} = Rel;
11433  let Inst{14-10} = 0b11111;
11434  let Inst{9-5} = Rn;
11435  let Inst{4-0} = Rt;
11436  let Predicates = [HasLSE];
11437}
11438
11439class BaseCAS<string order, string size, RegisterClass RC>
11440      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11441                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11442                        "$out = $Rs",[]>,
11443        Sched<[WriteAtomic]> {
11444  let NP = 1;
11445}
11446
11447multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11448  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11449  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11450  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11451  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11452}
11453
11454class BaseCASP<string order, string size, RegisterOperand RC>
11455      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11456                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11457                        "$out = $Rs",[]>,
11458        Sched<[WriteAtomic]> {
11459  let NP = 0;
11460}
11461
11462multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11463  let Sz = 0b00, Acq = Acq, Rel = Rel in
11464    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11465  let Sz = 0b01, Acq = Acq, Rel = Rel in
11466    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11467}
11468
11469let Predicates = [HasLSE] in
11470class BaseSWP<string order, string size, RegisterClass RC>
11471      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11472          "\t$Rs, $Rt, [$Rn]","",[]>,
11473        Sched<[WriteAtomic]> {
11474  bits<2> Sz;
11475  bit Acq;
11476  bit Rel;
11477  bits<5> Rs;
11478  bits<3> opc = 0b000;
11479  bits<5> Rn;
11480  bits<5> Rt;
11481  let Inst{31-30} = Sz;
11482  let Inst{29-24} = 0b111000;
11483  let Inst{23} = Acq;
11484  let Inst{22} = Rel;
11485  let Inst{21} = 0b1;
11486  let Inst{20-16} = Rs;
11487  let Inst{15} = 0b1;
11488  let Inst{14-12} = opc;
11489  let Inst{11-10} = 0b00;
11490  let Inst{9-5} = Rn;
11491  let Inst{4-0} = Rt;
11492  let Predicates = [HasLSE];
11493}
11494
11495multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11496  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11497  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11498  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11499  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11500}
11501
11502let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11503class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11504      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11505          "\t$Rs, $Rt, [$Rn]","",[]>,
11506        Sched<[WriteAtomic]> {
11507  bits<2> Sz;
11508  bit Acq;
11509  bit Rel;
11510  bits<5> Rs;
11511  bits<3> opc;
11512  bits<5> Rn;
11513  bits<5> Rt;
11514  let Inst{31-30} = Sz;
11515  let Inst{29-24} = 0b111000;
11516  let Inst{23} = Acq;
11517  let Inst{22} = Rel;
11518  let Inst{21} = 0b1;
11519  let Inst{20-16} = Rs;
11520  let Inst{15} = 0b0;
11521  let Inst{14-12} = opc;
11522  let Inst{11-10} = 0b00;
11523  let Inst{9-5} = Rn;
11524  let Inst{4-0} = Rt;
11525  let Predicates = [HasLSE];
11526}
11527
11528multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11529                        string order> {
11530  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11531    def B : BaseLDOPregister<op, order, "b", GPR32>;
11532  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11533    def H : BaseLDOPregister<op, order, "h", GPR32>;
11534  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11535    def W : BaseLDOPregister<op, order, "", GPR32>;
11536  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11537    def X : BaseLDOPregister<op, order, "", GPR64>;
11538}
11539
11540// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11541// complex DAG for DstRHS.
11542let Predicates = [HasLSE] in
11543multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11544                                         string size, dag SrcRHS, dag DstRHS> {
11545  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11546            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11547  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11548            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11549  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11550            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11551  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11552            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11553  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11554            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11555}
11556
11557multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11558                                     string size, dag RHS> {
11559  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11560}
11561
11562multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11563                                         string size, dag LHS, dag RHS> {
11564  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11565}
11566
11567multiclass LDOPregister_patterns<string inst, string op> {
11568  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11569  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11570  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11571  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11572}
11573
11574multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11575  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11576                        (i64 GPR64:$Rm),
11577                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11578  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11579                        (i32 GPR32:$Rm),
11580                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11581  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11582                        (i32 GPR32:$Rm),
11583                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11584  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11585                        (i32 GPR32:$Rm),
11586                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11587}
11588
11589let Predicates = [HasLSE] in
11590multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11591                                        string size, dag OLD, dag NEW> {
11592  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11593            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11594  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11595            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11596  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11597            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11598  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11599            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11600  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11601            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11602}
11603
11604multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11605                                    string size, dag OLD, dag NEW> {
11606  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11607}
11608
11609multiclass CASregister_patterns<string inst, string op> {
11610  defm : CASregister_patterns_ord<inst, "X", op, "64",
11611                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11612  defm : CASregister_patterns_ord<inst, "W", op, "32",
11613                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11614  defm : CASregister_patterns_ord<inst, "H", op, "16",
11615                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11616  defm : CASregister_patterns_ord<inst, "B", op, "8",
11617                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11618}
11619
11620let Predicates = [HasLSE] in
11621class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11622                        Instruction inst> :
11623      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11624
11625multiclass STOPregister<string asm, string instr> {
11626  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11627                    !cast<Instruction>(instr # "LB")>;
11628  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11629                    !cast<Instruction>(instr # "LH")>;
11630  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11631                    !cast<Instruction>(instr # "LW")>;
11632  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11633                    !cast<Instruction>(instr # "LX")>;
11634  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11635                    !cast<Instruction>(instr # "B")>;
11636  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11637                    !cast<Instruction>(instr # "H")>;
11638  def : BaseSTOPregister<asm,        GPR32, WZR,
11639                    !cast<Instruction>(instr # "W")>;
11640  def : BaseSTOPregister<asm,        GPR64, XZR,
11641                    !cast<Instruction>(instr # "X")>;
11642}
11643
11644class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11645                        dag iops, dag oops, list<dag> pat>
11646    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11647      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11648  bits<5> Rt;
11649  bits<5> Rn;
11650  let Inst{31-21} = 0b11111000001;
11651  let Inst{15}    = 1;
11652  let Inst{14-12} = opc;
11653  let Inst{11-10} = 0b00;
11654  let Inst{9-5}   = Rn;
11655  let Inst{4-0}   = Rt;
11656
11657  let Predicates = [HasV8_7a];
11658}
11659
11660class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11661                      list<dag> pat = []>
11662    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11663  let Inst{20-16} = 0b11111;
11664}
11665
11666class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11667    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11668                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11669  bits<5> Rs;
11670  let Inst{20-16} = Rs;
11671}
11672
11673class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11674                             bits<2> op2, string asm>
11675  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11676      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11677      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11678      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11679    Sched<[]> {
11680  bits<5> Rd;
11681  bits<5> Rs;
11682  bits<5> Rn;
11683  let Inst{31-27} = 0b00011;
11684  let Inst{26} = isMove;
11685  let Inst{25-24} = 0b01;
11686  let Inst{23-22} = opcode;
11687  let Inst{21} = 0b0;
11688  let Inst{20-16} = Rs;
11689  let Inst{15-14} = op2;
11690  let Inst{13-12} = op1;
11691  let Inst{11-10} = 0b01;
11692  let Inst{9-5} = Rn;
11693  let Inst{4-0} = Rd;
11694
11695  let DecoderMethod = "DecodeCPYMemOpInstruction";
11696  let mayLoad = 1;
11697  let mayStore = 1;
11698}
11699
11700class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11701  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11702
11703class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11704  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11705
11706class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11707                        string asm>
11708  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11709      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11710      asm, "\t[$Rd]!, $Rn!, $Rm",
11711      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11712    Sched<[]> {
11713  bits<5> Rd;
11714  bits<5> Rn;
11715  bits<5> Rm;
11716  let Inst{31-27} = 0b00011;
11717  let Inst{26} = isTagging;
11718  let Inst{25-21} = 0b01110;
11719  let Inst{20-16} = Rm;
11720  let Inst{15-14} = opcode;
11721  let Inst{13} = op2;
11722  let Inst{12} = op1;
11723  let Inst{11-10} = 0b01;
11724  let Inst{9-5} = Rn;
11725  let Inst{4-0} = Rd;
11726
11727  let DecoderMethod = "DecodeSETMemOpInstruction";
11728  let mayLoad = 0;
11729  let mayStore = 1;
11730}
11731
11732class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
11733  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
11734
11735class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
11736  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
11737
11738multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
11739  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
11740  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
11741  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
11742  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
11743  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
11744  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
11745  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
11746  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
11747  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
11748  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
11749  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
11750  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
11751  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
11752  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
11753  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
11754  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
11755}
11756
11757multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
11758  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
11759  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
11760  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
11761  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
11762  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
11763  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
11764  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
11765  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
11766  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
11767  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
11768  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
11769  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
11770  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
11771  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
11772  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
11773  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
11774}
11775
11776multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
11777  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
11778  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
11779  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
11780  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
11781}
11782
11783multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
11784  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
11785  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
11786  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
11787  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
11788}
11789
11790//----------------------------------------------------------------------------
11791// 2022 Armv8.9/Armv9.4 Extensions
11792//----------------------------------------------------------------------------
11793
11794//---
11795// 2022 Architecture Extensions: General Data Processing (FEAT_CSSC)
11796//---
11797
11798class BaseTwoOperandRegImm<bit sf, bit Op, bit S, bits<4> opc,
11799                           RegisterClass regtype, ImmLeaf immtype, string asm,
11800                           SDPatternOperator OpNode>
11801    : I<(outs regtype:$Rd), (ins regtype:$Rn, immtype:$imm),
11802        asm, "\t$Rd, $Rn, $imm", "",
11803        [(set regtype:$Rd, (OpNode regtype:$Rn, immtype:$imm))]> {
11804  bits<5> Rd;
11805  bits<5> Rn;
11806  bits<8> imm;
11807
11808  let Inst{31}    = sf;
11809  let Inst{30}    = Op;
11810  let Inst{29}    = S;
11811  let Inst{28-22} = 0b1000111;
11812  let Inst{21-18} = opc;
11813  let Inst{17-10} = imm;
11814  let Inst{9-5}   = Rn;
11815  let Inst{4-0}   = Rd;
11816}
11817
11818class BaseComparisonOpReg<bit size, bit isUnsigned, bit isMin,
11819                          RegisterClass regtype, string asm,
11820                          SDPatternOperator OpNode>
11821    : BaseTwoOperandRegReg<size, 0b0, {0,1,1,0,?,?}, regtype, asm, OpNode>,
11822      Sched<[WriteI]> {
11823  let Inst{11} = isMin;
11824  let Inst{10} = isUnsigned;
11825  let mayLoad  = 0;
11826  let mayStore = 0;
11827  let hasSideEffects = 0;
11828}
11829
11830class BaseComparisonOpImm<bit size, bit isUnsigned, bit isMin,
11831                          RegisterClass regtype, ImmLeaf immtype, string asm,
11832                          SDPatternOperator OpNode>
11833    : BaseTwoOperandRegImm<size, 0b0, 0b0, {0,0,?,?}, regtype, immtype, asm,
11834                           OpNode>,
11835      Sched<[]> {
11836  let Inst{19} = isMin;
11837  let Inst{18} = isUnsigned;
11838  let mayLoad  = 0;
11839  let mayStore = 0;
11840  let hasSideEffects = 0;
11841}
11842
11843multiclass ComparisonOp<bit isUnsigned, bit isMin, string asm,
11844                        SDPatternOperator OpNode = null_frag> {
11845  def Wrr : BaseComparisonOpReg<0b0, isUnsigned, isMin, GPR32, asm, OpNode>;
11846
11847  def Wri : BaseComparisonOpImm<0b0, isUnsigned, isMin, GPR32,
11848                                !cond(isUnsigned : uimm8_32b,
11849                                      !not(isUnsigned) : simm8_32b), asm, OpNode>;
11850
11851  def Xrr : BaseComparisonOpReg<0b1, isUnsigned, isMin, GPR64, asm, OpNode>;
11852
11853  def Xri : BaseComparisonOpImm<0b1, isUnsigned, isMin, GPR64,
11854                                !cond(isUnsigned : uimm8_64b,
11855                                      !not(isUnsigned) : simm8_64b), asm, OpNode>;
11856}
11857
11858//---
11859// RCPC instructions (FEAT_LRCPC3)
11860//---
11861
11862class BaseLRCPC3<bits<2> size, bit V, bits<2> opc, dag oops, dag iops,
11863                 string asm, string operands, string cstr = "">
11864      : I<oops, iops, asm, operands, cstr, []>,
11865        Sched<[WriteAtomic]> {
11866  bits<5> Rt;
11867  bits<5> Rn;
11868  let Inst{31-30}    = size;
11869  let Inst{29-24}    = {0,1,1,V,0,1};
11870  let Inst{23-22}    = opc;
11871  let Inst{21}       = 0b0;
11872  //  Inst{20-12}
11873  let Inst{11-10}    = 0b10;
11874  let Inst{9-5}      = Rn;
11875  let Inst{4-0}      = Rt;
11876
11877  let mayLoad = Inst{22};
11878  let mayStore = !not(Inst{22});
11879  let hasSideEffects = 0;
11880}
11881
11882class BaseLRCPC3IntegerLoadStorePair<bits<2> size, bits<2> opc, bits<4> opc2,
11883                                     dag oops, dag iops, string asm,
11884                                     string operands, string cstr>
11885      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
11886  bits<5> Rt2;
11887  let Inst{20-16} = Rt2;
11888  let Inst{15-12} = opc2;
11889}
11890
11891class BaseLRCPC3IntegerLoadStore<bits<2> size, bits<2> opc, dag oops, dag iops,
11892                                 string asm, string operands, string cstr>
11893      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
11894  let Inst{20-12} = 0b000000000; // imm9
11895}
11896
11897multiclass LRCPC3NEONLoadStoreUnscaledOffset<bits<2> size, bits<2> opc, RegisterClass regtype,
11898                                             dag oops, dag iops, string asm> {
11899  def i : BaseLRCPC3<size, /*V*/1, opc, oops, iops, asm, "\t$Rt, [$Rn{, $simm}]", /*cstr*/""> {
11900    bits<9> simm; // signed immediate encoded in imm9=Rt2:imm4
11901    let Inst{20-12} = simm;
11902  }
11903
11904  def a : InstAlias<asm # "\t$Rt, [$Rn]",
11905                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
11906}
11907
11908class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
11909      : BaseSIMDLdStSingle<L, /*R*/0b0, /*opcode*/0b100, asm,
11910                           "\t$Vt$Q, [$Rn]", cst, oops, iops, []>,
11911        Sched<[]> {
11912  bit Q;
11913  let Inst{31}       = 0;
11914  let Inst{30}       = Q;
11915  let Inst{23}       = 0;
11916  let Inst{20-16}    = 0b00001;
11917  let Inst{12}       = 0; // S
11918  let Inst{11-10}    = 0b01; // size
11919
11920  let mayLoad = L;
11921  let mayStore = !not(L);
11922  let hasSideEffects = 1;
11923}
11924
11925//---
11926// Instrumentation Extension (FEAT_ITE)
11927//---
11928
11929let Predicates = [HasITE] in
11930def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
11931  let Inst{20-19} = 0b01;
11932  let Inst{18-16} = 0b011;
11933  let Inst{15-12} = 0b0111;
11934  let Inst{11-8}  = 0b0010;
11935  let Inst{7-5}   = 0b111;
11936}
11937
11938// * RCWCAS family
11939// * RCW<OP> family
11940
11941//--------------------------------------------------------------------
11942// Read-Check-Write Compare And Swap family (RCWCAS[S|P|PS]?[A|L|AL]?)
11943
11944// Instruction encoding:
11945//
11946//          31 30|29  24|23|22|21|20 16|15|14 13|12 11 10|9 5|4 0
11947// RCWCAS    0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
11948// RCWSCAS   0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
11949// RCWCASP   0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
11950// RCWSCASP  0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
11951
11952// Instruction syntax:
11953//
11954// RCW[S]CAS{<order>}   <Xs>,           <Xt>,          [<Xn|SP>]
11955// RCW[S]CASP{<order>}  <Xs>, <X(s+1)>, <Xt>, <X(t+1)> [<Xn|SP>]
11956
11957class BaseRCWCASEncoding<dag oops, dag iops, string asm>
11958      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", "$out = $Rs", []>,
11959        Sched<[]> {
11960  bit Acq;
11961  bit Rel;
11962  bit SC;
11963  bit Pair;
11964  bits<5> Rs;
11965  bits<5> Rn;
11966  bits<5> Rt;
11967  let Inst{31} = 0b0;
11968  let Inst{30} = SC;
11969  let Inst{29-24} = 0b011001;
11970  let Inst{23} = Acq;
11971  let Inst{22} = Rel;
11972  let Inst{21} = 0b1;
11973  let Inst{20-16} = Rs;
11974  let Inst{15-13} = 0b000;
11975  let Inst{12-11} = 0b01;
11976  let Inst{10} = Pair;
11977  let Inst{9-5} = Rn;
11978  let Inst{4-0} = Rt;
11979  let mayLoad = 1;
11980  let mayStore = 1;
11981  let hasSideEffects = 1;
11982  let Defs = [NZCV];
11983}
11984
11985multiclass BaseRCWCAS<dag oops, dag iops, string prefix> {
11986  let Acq = 0b0, Rel = 0b0 in
11987    def "" : BaseRCWCASEncoding<oops, iops, prefix # "">;
11988  let Acq = 0b1, Rel = 0b0 in
11989    def A  : BaseRCWCASEncoding<oops, iops, prefix # "a">;
11990  let Acq = 0b0, Rel = 0b1 in
11991    def L  : BaseRCWCASEncoding<oops, iops, prefix # "l">;
11992  let Acq = 0b1, Rel = 0b1 in
11993    def AL : BaseRCWCASEncoding<oops, iops, prefix # "al">;
11994}
11995
11996multiclass ReadCheckWriteCompareAndSwap {
11997  let SC = 0b0, Pair = 0b0, Predicates = [HasTHE] in
11998    defm CAS  : BaseRCWCAS<(outs GPR64:$out),
11999                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwcas" >;
12000  let SC = 0b1, Pair = 0b0, Predicates = [HasTHE] in
12001    defm SCAS : BaseRCWCAS<(outs GPR64:$out),
12002                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwscas">;
12003  let SC = 0b0, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12004    defm CASP : BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12005                           (ins XSeqPairClassOperand:$Rs,
12006                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12007                           "rcwcasp">;
12008  let SC = 0b1, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12009    defm SCASP: BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12010                           (ins XSeqPairClassOperand:$Rs,
12011                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12012                           "rcwscasp">;
12013}
12014
12015//------------------------------------------------------------------
12016// Read-Check-Write <OP> family (RCW[CLR|SET|SWP][S|P|PS]?[A|L|AL]?)
12017
12018// Instruction encoding:
12019//
12020//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12021// RCWCLR    0  0|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12022// RCWSCLR   0  1|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12023// RCWSET    0  0|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12024// RCWSSET   0  1|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12025// RCWSWP    0  0|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12026// RCWSSWP   0  1|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12027
12028//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12029// RCWCLRP   0  0|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12030// RCWSCLRP  0  1|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12031// RCWSETP   0  0|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12032// RCWSSETP  0  1|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12033// RCWSWPP   0  0|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12034// RCWSSWPP  0  1|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12035
12036// Instruction syntax:
12037//
12038// RCW[S]<OP>{<order>}   <Xs>,  <Xt>, [<Xn|SP>]
12039// RCW[S]<OP>P{<order>}  <Xt1>, <Xt2>, [<Xn|SP>]
12040
12041class BaseRCWOPEncoding<string asm>
12042      : I<(outs GPR64:$Rt),(ins GPR64:$Rs, GPR64sp:$Rn), asm,
12043          "\t$Rs, $Rt, [$Rn]", "", []>,
12044        Sched<[]> {
12045  bit Acq;
12046  bit Rel;
12047  bit SC;
12048  bits<3> opc;
12049  bits<5> Rs;
12050  bits<5> Rn;
12051  bits<5> Rt;
12052  let Inst{31} = 0b0;
12053  let Inst{30} = SC;
12054  let Inst{29-24} = 0b111000;
12055  let Inst{23} = Acq;
12056  let Inst{22} = Rel;
12057  let Inst{21} = 0b1;
12058  let Inst{20-16} = Rs;
12059  let Inst{15} = 0b1;
12060  let Inst{14-12} = opc;
12061  let Inst{11-10} = 0b00;
12062  let Inst{9-5} = Rn;
12063  let Inst{4-0} = Rt;
12064  let mayLoad = 1;
12065  let mayStore = 1;
12066  let hasSideEffects = 1;
12067  let Defs = [NZCV];
12068  let Predicates = [HasTHE];
12069}
12070
12071class BaseRCWOPPEncoding<string asm>
12072      : I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12073          (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn), asm,
12074          "\t$Rt, $Rt2, [$Rn]", "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12075        Sched<[]> {
12076  bit Acq;
12077  bit Rel;
12078  bit SC;
12079  bits<3> opc;
12080  bits<5> Rt2;
12081  bits<5> Rn;
12082  bits<5> Rt;
12083  let Inst{31} = 0b0;
12084  let Inst{30} = SC;
12085  let Inst{29-24} = 0b011001;
12086  let Inst{23} = Acq;
12087  let Inst{22} = Rel;
12088  let Inst{21} = 0b1;
12089  let Inst{20-16} = Rt2;
12090  let Inst{15} = 0b1;
12091  let Inst{14-12} = opc;
12092  let Inst{11-10} = 0b00;
12093  let Inst{9-5} = Rn;
12094  let Inst{4-0} = Rt;
12095  let mayLoad = 1;
12096  let mayStore = 1;
12097  let hasSideEffects = 1;
12098  let Defs = [NZCV];
12099  let Predicates = [HasTHE, HasD128];
12100}
12101
12102multiclass BaseRCWOP<string prefix> {
12103  let Acq = 0b0, Rel = 0b0 in def "" : BaseRCWOPEncoding<prefix # "">;
12104  let Acq = 0b1, Rel = 0b0 in def A  : BaseRCWOPEncoding<prefix # "a">;
12105  let Acq = 0b0, Rel = 0b1 in def L  : BaseRCWOPEncoding<prefix # "l">;
12106  let Acq = 0b1, Rel = 0b1 in def AL : BaseRCWOPEncoding<prefix # "al">;
12107
12108  let Acq = 0b0, Rel = 0b0 in def P   : BaseRCWOPPEncoding<prefix # "p">;
12109  let Acq = 0b1, Rel = 0b0 in def PA  : BaseRCWOPPEncoding<prefix # "pa">;
12110  let Acq = 0b0, Rel = 0b1 in def PL  : BaseRCWOPPEncoding<prefix # "pl">;
12111  let Acq = 0b1, Rel = 0b1 in def PAL : BaseRCWOPPEncoding<prefix # "pal">;
12112}
12113
12114multiclass ReadCheckWriteOperation<bits<3> opc, string op> {
12115  let SC = 0b0, opc = opc in defm ""  : BaseRCWOP<"rcw" # ""  # op>;
12116  let SC = 0b1, opc = opc in defm S   : BaseRCWOP<"rcw" # "s" # op >;
12117}
12118
12119//---
12120// 128-bit atomic instructions (FEAT_LSE128)
12121//---
12122
12123let mayLoad = 1, mayStore = 1, hasSideEffects = 0 in
12124class LSE128Base<bits<3> op0, bits<2> AR, bit o3, string asm>
12125: I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12126    (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn),
12127    asm, "\t$Rt, $Rt2, [$Rn]",
12128    "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12129  Sched<[]> {
12130  bits<5> Rt;
12131  bits<5> Rt2;
12132  bits<5> Rn;
12133  let Inst{31-24} = 0b00011001;
12134  let Inst{23-22} = AR;
12135  let Inst{21} = 0b1;
12136  let Inst{20-16} = Rt2;
12137  let Inst{15} = o3;
12138  let Inst{14-12} = op0;
12139  let Inst{11-10} = 0b00;
12140  let Inst{9-5} = Rn;
12141  let Inst{4-0} = Rt;
12142}
12143
12144//---
12145// 128-bit System Instructions (FEAT_SYSINSTR128)
12146//---
12147
12148// Instruction encoding:
12149//
12150//          31          19|18 16|15 12|11 8|7 5|4 0
12151// SYSP      1101010101001|  op1|   Cn|  Cm|op2| Rt
12152
12153// Instruction syntax:
12154//
12155// SYSP #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>, <Xt+1>}
12156
12157class RtSystemI128<bit L, dag oops, dag iops, string asm, string operands, list<dag> pattern = []> :
12158  RtSystemI<L, oops, iops, asm, operands, pattern> {
12159  let Inst{22}    = 0b1; // override BaseSystemI
12160}
12161
12162class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inputs>
12163  : RtSystemI128<L, outputs, inputs, asm, operands> {
12164  bits<3> op1;
12165  bits<4> Cn;
12166  bits<4> Cm;
12167  bits<3> op2;
12168  let Inst{20-19} = 0b01;
12169  let Inst{18-16} = op1;
12170  let Inst{15-12} = Cn;
12171  let Inst{11-8}  = Cm;
12172  let Inst{7-5}   = op2;
12173}
12174class SystemPXtI<bit L, string asm> :
12175  BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
12176  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
12177
12178
12179//----------------------------------------------------------------------------
12180// Allow the size specifier tokens to be upper case, not just lower.
12181def : TokenAlias<".4B", ".4b">;  // Add dot product
12182def : TokenAlias<".8B", ".8b">;
12183def : TokenAlias<".4H", ".4h">;
12184def : TokenAlias<".2S", ".2s">;
12185def : TokenAlias<".1D", ".1d">;
12186def : TokenAlias<".16B", ".16b">;
12187def : TokenAlias<".8H", ".8h">;
12188def : TokenAlias<".4S", ".4s">;
12189def : TokenAlias<".2D", ".2d">;
12190def : TokenAlias<".1Q", ".1q">;
12191def : TokenAlias<".2H", ".2h">;
12192def : TokenAlias<".B", ".b">;
12193def : TokenAlias<".H", ".h">;
12194def : TokenAlias<".S", ".s">;
12195def : TokenAlias<".D", ".d">;
12196def : TokenAlias<".Q", ".q">;
12197