xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
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_dup_v8i16 :
137   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
138def extract_high_dup_v4i32 :
139   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
140
141//===----------------------------------------------------------------------===//
142// Asm Operand Classes.
143//
144
145// Shifter operand for arithmetic shifted encodings.
146def ShifterOperand : AsmOperandClass {
147  let Name = "Shifter";
148}
149
150// Shifter operand for mov immediate encodings.
151def MovImm32ShifterOperand : AsmOperandClass {
152  let SuperClasses = [ShifterOperand];
153  let Name = "MovImm32Shifter";
154  let RenderMethod = "addShifterOperands";
155  let DiagnosticType = "InvalidMovImm32Shift";
156}
157def MovImm64ShifterOperand : AsmOperandClass {
158  let SuperClasses = [ShifterOperand];
159  let Name = "MovImm64Shifter";
160  let RenderMethod = "addShifterOperands";
161  let DiagnosticType = "InvalidMovImm64Shift";
162}
163
164// Shifter operand for arithmetic register shifted encodings.
165class ArithmeticShifterOperand<int width> : AsmOperandClass {
166  let SuperClasses = [ShifterOperand];
167  let Name = "ArithmeticShifter" # width;
168  let PredicateMethod = "isArithmeticShifter<" # width # ">";
169  let RenderMethod = "addShifterOperands";
170  let DiagnosticType = "AddSubRegShift" # width;
171}
172
173def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
174def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
175
176// Shifter operand for logical register shifted encodings.
177class LogicalShifterOperand<int width> : AsmOperandClass {
178  let SuperClasses = [ShifterOperand];
179  let Name = "LogicalShifter" # width;
180  let PredicateMethod = "isLogicalShifter<" # width # ">";
181  let RenderMethod = "addShifterOperands";
182  let DiagnosticType = "AddSubRegShift" # width;
183}
184
185def LogicalShifterOperand32 : LogicalShifterOperand<32>;
186def LogicalShifterOperand64 : LogicalShifterOperand<64>;
187
188// Shifter operand for logical vector 128/64-bit shifted encodings.
189def LogicalVecShifterOperand : AsmOperandClass {
190  let SuperClasses = [ShifterOperand];
191  let Name = "LogicalVecShifter";
192  let RenderMethod = "addShifterOperands";
193}
194def LogicalVecHalfWordShifterOperand : AsmOperandClass {
195  let SuperClasses = [LogicalVecShifterOperand];
196  let Name = "LogicalVecHalfWordShifter";
197  let RenderMethod = "addShifterOperands";
198}
199
200// The "MSL" shifter on the vector MOVI instruction.
201def MoveVecShifterOperand : AsmOperandClass {
202  let SuperClasses = [ShifterOperand];
203  let Name = "MoveVecShifter";
204  let RenderMethod = "addShifterOperands";
205}
206
207// Extend operand for arithmetic encodings.
208def ExtendOperand : AsmOperandClass {
209  let Name = "Extend";
210  let DiagnosticType = "AddSubRegExtendLarge";
211}
212def ExtendOperand64 : AsmOperandClass {
213  let SuperClasses = [ExtendOperand];
214  let Name = "Extend64";
215  let DiagnosticType = "AddSubRegExtendSmall";
216}
217// 'extend' that's a lsl of a 64-bit register.
218def ExtendOperandLSL64 : AsmOperandClass {
219  let SuperClasses = [ExtendOperand];
220  let Name = "ExtendLSL64";
221  let RenderMethod = "addExtend64Operands";
222  let DiagnosticType = "AddSubRegExtendLarge";
223}
224
225// 8-bit floating-point immediate encodings.
226def FPImmOperand : AsmOperandClass {
227  let Name = "FPImm";
228  let ParserMethod = "tryParseFPImm<true>";
229  let DiagnosticType = "InvalidFPImm";
230}
231
232def CondCode : AsmOperandClass {
233  let Name = "CondCode";
234  let DiagnosticType = "InvalidCondCode";
235}
236
237// A 32-bit register pasrsed as 64-bit
238def GPR32as64Operand : AsmOperandClass {
239  let Name = "GPR32as64";
240  let ParserMethod =
241      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
242}
243def GPR32as64 : RegisterOperand<GPR32> {
244  let ParserMatchClass = GPR32as64Operand;
245}
246
247// A 64-bit register pasrsed as 32-bit
248def GPR64as32Operand : AsmOperandClass {
249  let Name = "GPR64as32";
250  let ParserMethod =
251      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
252}
253def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
254  let ParserMatchClass = GPR64as32Operand;
255}
256
257// 8-bit immediate for AdvSIMD where 64-bit values of the form:
258// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
259// are encoded as the eight bit value 'abcdefgh'.
260def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
261
262class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
263  let Name = "UImm" # Width # "s" # Scale;
264  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
265  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
266  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
267}
268
269class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
270  let Name = "SImm" # Width # "s" # Scale;
271  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
272  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
273  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
274}
275
276//===----------------------------------------------------------------------===//
277// Operand Definitions.
278//
279
280// ADR[P] instruction labels.
281def AdrpOperand : AsmOperandClass {
282  let Name = "AdrpLabel";
283  let ParserMethod = "tryParseAdrpLabel";
284  let DiagnosticType = "InvalidLabel";
285}
286def adrplabel : Operand<i64> {
287  let EncoderMethod = "getAdrLabelOpValue";
288  let PrintMethod = "printAdrpLabel";
289  let ParserMatchClass = AdrpOperand;
290  let OperandType = "OPERAND_PCREL";
291}
292
293def AdrOperand : AsmOperandClass {
294  let Name = "AdrLabel";
295  let ParserMethod = "tryParseAdrLabel";
296  let DiagnosticType = "InvalidLabel";
297}
298def adrlabel : Operand<i64> {
299  let EncoderMethod = "getAdrLabelOpValue";
300  let ParserMatchClass = AdrOperand;
301}
302
303class SImmOperand<int width> : AsmOperandClass {
304  let Name = "SImm" # width;
305  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
306  let RenderMethod = "addImmOperands";
307  let PredicateMethod = "isSImm<" # width # ">";
308}
309
310class AsmImmRange<int Low, int High> : AsmOperandClass {
311  let Name = "Imm" # Low # "_" # High;
312  let DiagnosticType = "InvalidImm" # Low # "_" # High;
313  let RenderMethod = "addImmOperands";
314  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
315}
316
317// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
318def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
319def simm10Scaled : Operand<i64> {
320  let ParserMatchClass = SImm10s8Operand;
321  let DecoderMethod = "DecodeSImm<10>";
322  let PrintMethod = "printImmScale<8>";
323}
324
325def simm9s16 : Operand<i64> {
326  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
327  let DecoderMethod = "DecodeSImm<9>";
328  let PrintMethod = "printImmScale<16>";
329}
330
331// uimm6 predicate - True if the immediate is in the range [0, 63].
332def UImm6Operand : AsmOperandClass {
333  let Name = "UImm6";
334  let DiagnosticType = "InvalidImm0_63";
335}
336
337def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
338  let ParserMatchClass = UImm6Operand;
339}
340
341def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
342  let ParserMatchClass = AsmImmRange<0, 65535>;
343}
344
345def SImm9Operand : SImmOperand<9>;
346def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
347  let ParserMatchClass = SImm9Operand;
348  let DecoderMethod = "DecodeSImm<9>";
349}
350
351// imm0_255 predicate - True if the immediate is in the range [0,255].
352def Imm0_255Operand : AsmImmRange<0,255>;
353
354def uimm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
355  let ParserMatchClass = Imm0_255Operand;
356}
357def uimm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
358  let ParserMatchClass = Imm0_255Operand;
359}
360
361def SImm8Operand : SImmOperand<8>;
362def simm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
363  let ParserMatchClass = SImm8Operand;
364  let DecoderMethod = "DecodeSImm<8>";
365}
366def simm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 128; }]> {
367  let ParserMatchClass = SImm8Operand;
368  let DecoderMethod = "DecodeSImm<8>";
369}
370
371def SImm6Operand : SImmOperand<6>;
372def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
373  let ParserMatchClass = SImm6Operand;
374  let DecoderMethod = "DecodeSImm<6>";
375}
376
377def SImm5Operand : SImmOperand<5>;
378def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
379  let ParserMatchClass = SImm5Operand;
380  let DecoderMethod = "DecodeSImm<5>";
381}
382
383def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
384  let ParserMatchClass = SImm5Operand;
385  let DecoderMethod = "DecodeSImm<5>";
386}
387
388def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
389  let ParserMatchClass = SImm5Operand;
390  let DecoderMethod = "DecodeSImm<5>";
391  let PrintMethod = "printSImm<8>";
392}
393
394def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
395  let ParserMatchClass = SImm5Operand;
396  let DecoderMethod = "DecodeSImm<5>";
397  let PrintMethod = "printSImm<16>";
398}
399
400// simm7sN predicate - True if the immediate is a multiple of N in the range
401// [-64 * N, 63 * N].
402
403def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
404def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
405def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
406
407def simm7s4 : Operand<i32> {
408  let ParserMatchClass = SImm7s4Operand;
409  let PrintMethod = "printImmScale<4>";
410}
411
412def simm7s8 : Operand<i32> {
413  let ParserMatchClass = SImm7s8Operand;
414  let PrintMethod = "printImmScale<8>";
415}
416
417def simm7s16 : Operand<i32> {
418  let ParserMatchClass = SImm7s16Operand;
419  let PrintMethod = "printImmScale<16>";
420}
421
422def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
423
424def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
425def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
426def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
427def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
428def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
429
430def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
431def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
432
433def UImmS1XForm : SDNodeXForm<imm, [{
434  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
435}]>;
436def UImmS2XForm : SDNodeXForm<imm, [{
437  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
438}]>;
439def UImmS4XForm : SDNodeXForm<imm, [{
440  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
441}]>;
442def UImmS8XForm : SDNodeXForm<imm, [{
443  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
444}]>;
445
446// uimm5sN predicate - True if the immediate is a multiple of N in the range
447// [0 * N, 32 * N].
448def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
449def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
450def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
451
452def uimm5s2 : Operand<i64>, ImmLeaf<i64,
453                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
454                UImmS2XForm> {
455  let ParserMatchClass = UImm5s2Operand;
456  let PrintMethod = "printImmScale<2>";
457}
458def uimm5s4 : Operand<i64>, ImmLeaf<i64,
459                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
460                UImmS4XForm> {
461  let ParserMatchClass = UImm5s4Operand;
462  let PrintMethod = "printImmScale<4>";
463}
464def uimm5s8 : Operand<i64>, ImmLeaf<i64,
465                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
466                UImmS8XForm> {
467  let ParserMatchClass = UImm5s8Operand;
468  let PrintMethod = "printImmScale<8>";
469}
470
471// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
472// instead of ImmLeaf (Constant)
473def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
474                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
475                UImmS2XForm> {
476  let ParserMatchClass = UImm5s2Operand;
477  let PrintMethod = "printImmScale<2>";
478}
479def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
480                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
481                UImmS4XForm> {
482  let ParserMatchClass = UImm5s4Operand;
483  let PrintMethod = "printImmScale<4>";
484}
485def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
486                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
487                UImmS8XForm> {
488  let ParserMatchClass = UImm5s8Operand;
489  let PrintMethod = "printImmScale<8>";
490}
491
492// uimm6sN predicate - True if the immediate is a multiple of N in the range
493// [0 * N, 64 * N].
494def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
495def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
496def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
497def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
498def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
499
500def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
501  let ParserMatchClass = UImm6s1Operand;
502}
503def uimm6s2 : Operand<i64>, ImmLeaf<i64,
504[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
505  let PrintMethod = "printImmScale<2>";
506  let ParserMatchClass = UImm6s2Operand;
507}
508def uimm6s4 : Operand<i64>, ImmLeaf<i64,
509[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
510  let PrintMethod = "printImmScale<4>";
511  let ParserMatchClass = UImm6s4Operand;
512}
513def uimm6s8 : Operand<i64>, ImmLeaf<i64,
514[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
515  let PrintMethod = "printImmScale<8>";
516  let ParserMatchClass = UImm6s8Operand;
517}
518def uimm6s16 : Operand<i64>, ImmLeaf<i64,
519[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
520  let PrintMethod = "printImmScale<16>";
521  let ParserMatchClass = UImm6s16Operand;
522}
523
524def SImmS2XForm : SDNodeXForm<imm, [{
525  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
526}]>;
527def SImmS3XForm : SDNodeXForm<imm, [{
528  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
529}]>;
530def SImmS4XForm : SDNodeXForm<imm, [{
531  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
532}]>;
533def SImmS16XForm : SDNodeXForm<imm, [{
534  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
535}]>;
536def SImmS32XForm : SDNodeXForm<imm, [{
537  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
538}]>;
539
540// simm6sN predicate - True if the immediate is a multiple of N in the range
541// [-32 * N, 31 * N].
542def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
543def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
544  let ParserMatchClass = SImm6s1Operand;
545  let DecoderMethod = "DecodeSImm<6>";
546}
547
548// simm4sN predicate - True if the immediate is a multiple of N in the range
549// [ -8* N, 7 * N].
550def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
551def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
552def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
553def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
554def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
555def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
556
557def simm4s1 : Operand<i64>, ImmLeaf<i64,
558[{ return Imm >=-8  && Imm <= 7; }]> {
559  let ParserMatchClass = SImm4s1Operand;
560  let DecoderMethod = "DecodeSImm<4>";
561}
562
563def simm4s2 : Operand<i64>, ImmLeaf<i64,
564[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
565  let PrintMethod = "printImmScale<2>";
566  let ParserMatchClass = SImm4s2Operand;
567  let DecoderMethod = "DecodeSImm<4>";
568}
569
570def simm4s3 : Operand<i64>, ImmLeaf<i64,
571[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
572  let PrintMethod = "printImmScale<3>";
573  let ParserMatchClass = SImm4s3Operand;
574  let DecoderMethod = "DecodeSImm<4>";
575}
576
577def simm4s4 : Operand<i64>, ImmLeaf<i64,
578[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
579  let PrintMethod = "printImmScale<4>";
580  let ParserMatchClass = SImm4s4Operand;
581  let DecoderMethod = "DecodeSImm<4>";
582}
583def simm4s16 : Operand<i64>, ImmLeaf<i64,
584[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
585  let PrintMethod = "printImmScale<16>";
586  let ParserMatchClass = SImm4s16Operand;
587  let DecoderMethod = "DecodeSImm<4>";
588}
589def simm4s32 : Operand<i64>, ImmLeaf<i64,
590[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
591  let PrintMethod = "printImmScale<32>";
592  let ParserMatchClass = SImm4s32Operand;
593  let DecoderMethod = "DecodeSImm<4>";
594}
595
596def Imm1_8Operand : AsmImmRange<1, 8>;
597def Imm1_16Operand : AsmImmRange<1, 16>;
598def Imm1_32Operand : AsmImmRange<1, 32>;
599def Imm1_64Operand : AsmImmRange<1, 64>;
600
601class BranchTarget<int N> : AsmOperandClass {
602  let Name = "BranchTarget" # N;
603  let DiagnosticType = "InvalidLabel";
604  let PredicateMethod = "isBranchTarget<" # N # ">";
605}
606
607class PCRelLabel<int N> : BranchTarget<N> {
608  let Name = "PCRelLabel" # N;
609}
610
611def BranchTarget14Operand : BranchTarget<14>;
612def BranchTarget26Operand : BranchTarget<26>;
613def PCRelLabel19Operand   : PCRelLabel<19>;
614
615def MovWSymbolG3AsmOperand : AsmOperandClass {
616  let Name = "MovWSymbolG3";
617  let RenderMethod = "addImmOperands";
618}
619
620def movw_symbol_g3 : Operand<i32> {
621  let ParserMatchClass = MovWSymbolG3AsmOperand;
622}
623
624def MovWSymbolG2AsmOperand : AsmOperandClass {
625  let Name = "MovWSymbolG2";
626  let RenderMethod = "addImmOperands";
627}
628
629def movw_symbol_g2 : Operand<i32> {
630  let ParserMatchClass = MovWSymbolG2AsmOperand;
631}
632
633def MovWSymbolG1AsmOperand : AsmOperandClass {
634  let Name = "MovWSymbolG1";
635  let RenderMethod = "addImmOperands";
636}
637
638def movw_symbol_g1 : Operand<i32> {
639  let ParserMatchClass = MovWSymbolG1AsmOperand;
640}
641
642def MovWSymbolG0AsmOperand : AsmOperandClass {
643  let Name = "MovWSymbolG0";
644  let RenderMethod = "addImmOperands";
645}
646
647def movw_symbol_g0 : Operand<i32> {
648  let ParserMatchClass = MovWSymbolG0AsmOperand;
649}
650
651class fixedpoint_i32<ValueType FloatVT>
652  : Operand<FloatVT>,
653    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
654  let EncoderMethod = "getFixedPointScaleOpValue";
655  let DecoderMethod = "DecodeFixedPointScaleImm32";
656  let ParserMatchClass = Imm1_32Operand;
657}
658
659class fixedpoint_i64<ValueType FloatVT>
660  : Operand<FloatVT>,
661    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
662  let EncoderMethod = "getFixedPointScaleOpValue";
663  let DecoderMethod = "DecodeFixedPointScaleImm64";
664  let ParserMatchClass = Imm1_64Operand;
665}
666
667def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
668def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
669def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
670
671def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
672def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
673def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
674
675def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
676  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
677}]> {
678  let EncoderMethod = "getVecShiftR8OpValue";
679  let DecoderMethod = "DecodeVecShiftR8Imm";
680  let ParserMatchClass = Imm1_8Operand;
681}
682def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
683  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
684}]> {
685  let EncoderMethod = "getVecShiftR16OpValue";
686  let DecoderMethod = "DecodeVecShiftR16Imm";
687  let ParserMatchClass = Imm1_16Operand;
688}
689def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
690  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
691}]> {
692  let EncoderMethod = "getVecShiftR16OpValue";
693  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
694  let ParserMatchClass = Imm1_8Operand;
695}
696def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
697  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
698}]> {
699  let EncoderMethod = "getVecShiftR32OpValue";
700  let DecoderMethod = "DecodeVecShiftR32Imm";
701  let ParserMatchClass = Imm1_32Operand;
702}
703def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
704  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
705}]> {
706  let EncoderMethod = "getVecShiftR32OpValue";
707  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
708  let ParserMatchClass = Imm1_16Operand;
709}
710def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
711  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
712}]> {
713  let EncoderMethod = "getVecShiftR64OpValue";
714  let DecoderMethod = "DecodeVecShiftR64Imm";
715  let ParserMatchClass = Imm1_64Operand;
716}
717def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
718  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
719}]> {
720  let EncoderMethod = "getVecShiftR64OpValue";
721  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
722  let ParserMatchClass = Imm1_32Operand;
723}
724
725// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
726// (ImmLeaf)
727def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
728  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
729}]> {
730  let EncoderMethod = "getVecShiftR8OpValue";
731  let DecoderMethod = "DecodeVecShiftR8Imm";
732  let ParserMatchClass = Imm1_8Operand;
733}
734def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
735  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
736}]> {
737  let EncoderMethod = "getVecShiftR16OpValue";
738  let DecoderMethod = "DecodeVecShiftR16Imm";
739  let ParserMatchClass = Imm1_16Operand;
740}
741def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
742  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
743}]> {
744  let EncoderMethod = "getVecShiftR32OpValue";
745  let DecoderMethod = "DecodeVecShiftR32Imm";
746  let ParserMatchClass = Imm1_32Operand;
747}
748def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
749  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
750}]> {
751  let EncoderMethod = "getVecShiftR64OpValue";
752  let DecoderMethod = "DecodeVecShiftR64Imm";
753  let ParserMatchClass = Imm1_64Operand;
754}
755
756def Imm0_0Operand : AsmImmRange<0, 0>;
757def Imm0_1Operand : AsmImmRange<0, 1>;
758def Imm0_3Operand : AsmImmRange<0, 3>;
759def Imm0_7Operand : AsmImmRange<0, 7>;
760def Imm0_15Operand : AsmImmRange<0, 15>;
761def Imm0_31Operand : AsmImmRange<0, 31>;
762def Imm0_63Operand : AsmImmRange<0, 63>;
763
764def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
765  return (((uint32_t)Imm) < 8);
766}]> {
767  let EncoderMethod = "getVecShiftL8OpValue";
768  let DecoderMethod = "DecodeVecShiftL8Imm";
769  let ParserMatchClass = Imm0_7Operand;
770}
771def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
772  return (((uint32_t)Imm) < 16);
773}]> {
774  let EncoderMethod = "getVecShiftL16OpValue";
775  let DecoderMethod = "DecodeVecShiftL16Imm";
776  let ParserMatchClass = Imm0_15Operand;
777}
778def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
779  return (((uint32_t)Imm) < 32);
780}]> {
781  let EncoderMethod = "getVecShiftL32OpValue";
782  let DecoderMethod = "DecodeVecShiftL32Imm";
783  let ParserMatchClass = Imm0_31Operand;
784}
785def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
786  return (((uint32_t)Imm) < 64);
787}]> {
788  let EncoderMethod = "getVecShiftL64OpValue";
789  let DecoderMethod = "DecodeVecShiftL64Imm";
790  let ParserMatchClass = Imm0_63Operand;
791}
792
793// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
794// (ImmLeaf)
795def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
796  return (((uint32_t)Imm) < 8);
797}]> {
798  let EncoderMethod = "getVecShiftL8OpValue";
799  let DecoderMethod = "DecodeVecShiftL8Imm";
800  let ParserMatchClass = Imm0_7Operand;
801}
802def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
803  return (((uint32_t)Imm) < 16);
804}]> {
805  let EncoderMethod = "getVecShiftL16OpValue";
806  let DecoderMethod = "DecodeVecShiftL16Imm";
807  let ParserMatchClass = Imm0_15Operand;
808}
809def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
810  return (((uint32_t)Imm) < 32);
811}]> {
812  let EncoderMethod = "getVecShiftL32OpValue";
813  let DecoderMethod = "DecodeVecShiftL32Imm";
814  let ParserMatchClass = Imm0_31Operand;
815}
816def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
817  return (((uint32_t)Imm) < 64);
818}]> {
819  let EncoderMethod = "getVecShiftL64OpValue";
820  let DecoderMethod = "DecodeVecShiftL64Imm";
821  let ParserMatchClass = Imm0_63Operand;
822}
823
824// Crazy immediate formats used by 32-bit and 64-bit logical immediate
825// instructions for splatting repeating bit patterns across the immediate.
826def logical_imm32_XFORM : SDNodeXForm<imm, [{
827  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
828  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
829}]>;
830def logical_imm64_XFORM : SDNodeXForm<imm, [{
831  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
832  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
833}]>;
834
835def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
836  GISDNodeXFormEquiv<logical_imm32_XFORM>;
837def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
838  GISDNodeXFormEquiv<logical_imm64_XFORM>;
839
840let DiagnosticType = "LogicalSecondSource" in {
841  def LogicalImm32Operand : AsmOperandClass {
842    let Name = "LogicalImm32";
843    let PredicateMethod = "isLogicalImm<int32_t>";
844    let RenderMethod = "addLogicalImmOperands<int32_t>";
845  }
846  def LogicalImm64Operand : AsmOperandClass {
847    let Name = "LogicalImm64";
848    let PredicateMethod = "isLogicalImm<int64_t>";
849    let RenderMethod = "addLogicalImmOperands<int64_t>";
850  }
851  def LogicalImm32NotOperand : AsmOperandClass {
852    let Name = "LogicalImm32Not";
853    let PredicateMethod = "isLogicalImm<int32_t>";
854    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
855  }
856  def LogicalImm64NotOperand : AsmOperandClass {
857    let Name = "LogicalImm64Not";
858    let PredicateMethod = "isLogicalImm<int64_t>";
859    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
860  }
861}
862def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
863  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
864}], logical_imm32_XFORM> {
865  let PrintMethod = "printLogicalImm<int32_t>";
866  let ParserMatchClass = LogicalImm32Operand;
867}
868def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
869  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
870}], logical_imm64_XFORM> {
871  let PrintMethod = "printLogicalImm<int64_t>";
872  let ParserMatchClass = LogicalImm64Operand;
873}
874def logical_imm32_not : Operand<i32> {
875  let ParserMatchClass = LogicalImm32NotOperand;
876}
877def logical_imm64_not : Operand<i64> {
878  let ParserMatchClass = LogicalImm64NotOperand;
879}
880
881// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
882let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
883def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
884  return ((uint32_t)Imm) < 65536;
885}]>;
886
887def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
888  return ((uint64_t)Imm) < 65536;
889}]>;
890}
891
892def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
893  return ((uint32_t)Imm) < 256;
894}]> {
895  let ParserMatchClass = Imm0_255Operand;
896  let PrintMethod = "printImm";
897}
898
899// imm0_127 predicate - True if the immediate is in the range [0,127]
900def Imm0_127Operand : AsmImmRange<0, 127>;
901def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
902  return ((uint32_t)Imm) < 128;
903}]> {
904  let ParserMatchClass = Imm0_127Operand;
905  let PrintMethod = "printImm";
906}
907
908def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
909  return ((uint64_t)Imm) < 128;
910}]> {
911  let ParserMatchClass = Imm0_127Operand;
912  let PrintMethod = "printImm";
913}
914
915// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
916// for all shift-amounts.
917
918// imm0_63 predicate - True if the immediate is in the range [0,63]
919def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
920  return ((uint64_t)Imm) < 64;
921}]> {
922  let ParserMatchClass = Imm0_63Operand;
923}
924
925def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
926  return ((uint64_t)Imm) < 64;
927}]> {
928  let ParserMatchClass = Imm0_63Operand;
929}
930
931// imm0_31 predicate - True if the immediate is in the range [0,31]
932def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
933  return ((uint64_t)Imm) < 32;
934}]> {
935  let ParserMatchClass = Imm0_31Operand;
936}
937
938// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
939// instead of Constant (ImmLeaf)
940def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
941  return ((uint64_t)Imm) < 32;
942}]> {
943  let ParserMatchClass = Imm0_31Operand;
944}
945
946// True if the 32-bit immediate is in the range [0,31]
947def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
948  return ((uint64_t)Imm) < 32;
949}]> {
950  let ParserMatchClass = Imm0_31Operand;
951}
952
953// imm0_1 predicate - True if the immediate is in the range [0,1]
954def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
955  return ((uint64_t)Imm) < 2;
956}]> {
957  let ParserMatchClass = Imm0_1Operand;
958}
959
960// timm0_1 - as above, but use TargetConstant (TImmLeaf)
961def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
962  return ((uint64_t)Imm) < 2;
963}]> {
964  let ParserMatchClass = Imm0_1Operand;
965}
966
967// timm32_0_1 predicate - True if the 32-bit immediate is in the range [0,1]
968def timm32_0_1 : Operand<i32>, TImmLeaf<i32, [{
969  return ((uint32_t)Imm) < 2;
970}]> {
971  let ParserMatchClass = Imm0_1Operand;
972}
973
974// imm0_15 predicate - True if the immediate is in the range [0,15]
975def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
976  return ((uint64_t)Imm) < 16;
977}]> {
978  let ParserMatchClass = Imm0_15Operand;
979}
980
981// imm0_7 predicate - True if the immediate is in the range [0,7]
982def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
983  return ((uint64_t)Imm) < 8;
984}]> {
985  let ParserMatchClass = Imm0_7Operand;
986}
987
988// imm0_3 predicate - True if the immediate is in the range [0,3]
989def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
990  return ((uint64_t)Imm) < 4;
991}]> {
992  let ParserMatchClass = Imm0_3Operand;
993}
994
995// timm32_0_3 predicate - True if the 32-bit immediate is in the range [0,3]
996def timm32_0_3 : Operand<i32>, TImmLeaf<i32, [{
997  return ((uint32_t)Imm) < 4;
998}]> {
999  let ParserMatchClass = Imm0_3Operand;
1000}
1001
1002// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
1003def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
1004  return ((uint32_t)Imm) < 8;
1005}]> {
1006  let ParserMatchClass = Imm0_7Operand;
1007}
1008
1009// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1010def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
1011  return ((uint32_t)Imm) < 16;
1012}]> {
1013  let ParserMatchClass = Imm0_15Operand;
1014}
1015
1016// timm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1017def timm32_0_15 : Operand<i32>, TImmLeaf<i32, [{
1018  return ((uint32_t)Imm) < 16;
1019}]> {
1020  let ParserMatchClass = Imm0_15Operand;
1021}
1022
1023// timm32_0_31 predicate - True if the 32-bit immediate is in the range [0,31]
1024def timm32_0_31 : Operand<i32>, TImmLeaf<i32, [{
1025  return ((uint32_t)Imm) < 32;
1026}]> {
1027  let ParserMatchClass = Imm0_31Operand;
1028}
1029
1030// timm32_0_255 predicate - True if the 32-bit immediate is in the range [0,255]
1031def timm32_0_255 : Operand<i32>, TImmLeaf<i32, [{
1032  return ((uint32_t)Imm) < 256;
1033}]> {
1034  let ParserMatchClass = Imm0_255Operand;
1035}
1036
1037// An arithmetic shifter operand:
1038//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
1039//  {5-0} - imm6
1040class arith_shift<ValueType Ty, int width> : Operand<Ty> {
1041  let PrintMethod = "printShifter";
1042  let ParserMatchClass = !cast<AsmOperandClass>(
1043                         "ArithmeticShifterOperand" # width);
1044}
1045
1046def arith_shift32 : arith_shift<i32, 32>;
1047def arith_shift64 : arith_shift<i64, 64>;
1048
1049class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
1050    : Operand<Ty>,
1051      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
1052  let PrintMethod = "printShiftedRegister";
1053  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
1054}
1055
1056def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
1057def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
1058
1059def gi_arith_shifted_reg32 :
1060  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1061  GIComplexPatternEquiv<arith_shifted_reg32>;
1062
1063def gi_arith_shifted_reg64 :
1064  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1065  GIComplexPatternEquiv<arith_shifted_reg64>;
1066
1067// An arithmetic shifter operand:
1068//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1069//  {5-0} - imm6
1070class logical_shift<int width> : Operand<i32> {
1071  let PrintMethod = "printShifter";
1072  let ParserMatchClass = !cast<AsmOperandClass>(
1073                         "LogicalShifterOperand" # width);
1074}
1075
1076def logical_shift32 : logical_shift<32>;
1077def logical_shift64 : logical_shift<64>;
1078
1079class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1080    : Operand<Ty>,
1081      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1082  let PrintMethod = "printShiftedRegister";
1083  let MIOperandInfo = (ops regclass, shiftop);
1084}
1085
1086def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1087def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1088
1089def gi_logical_shifted_reg32 :
1090  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1091  GIComplexPatternEquiv<logical_shifted_reg32>;
1092
1093def gi_logical_shifted_reg64 :
1094  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1095  GIComplexPatternEquiv<logical_shifted_reg64>;
1096
1097// A logical vector shifter operand:
1098//  {7-6} - shift type: 00 = lsl
1099//  {5-0} - imm6: #0, #8, #16, or #24
1100def logical_vec_shift : Operand<i32> {
1101  let PrintMethod = "printShifter";
1102  let EncoderMethod = "getVecShifterOpValue";
1103  let ParserMatchClass = LogicalVecShifterOperand;
1104}
1105
1106// A logical vector half-word shifter operand:
1107//  {7-6} - shift type: 00 = lsl
1108//  {5-0} - imm6: #0 or #8
1109def logical_vec_hw_shift : Operand<i32> {
1110  let PrintMethod = "printShifter";
1111  let EncoderMethod = "getVecShifterOpValue";
1112  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1113}
1114
1115// A vector move shifter operand:
1116//  {0} - imm1: #8 or #16
1117def move_vec_shift : Operand<i32> {
1118  let PrintMethod = "printShifter";
1119  let EncoderMethod = "getMoveVecShifterOpValue";
1120  let ParserMatchClass = MoveVecShifterOperand;
1121}
1122
1123let DiagnosticType = "AddSubSecondSource" in {
1124  def AddSubImmOperand : AsmOperandClass {
1125    let Name = "AddSubImm";
1126    let ParserMethod = "tryParseImmWithOptionalShift";
1127    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1128  }
1129  def AddSubImmNegOperand : AsmOperandClass {
1130    let Name = "AddSubImmNeg";
1131    let ParserMethod = "tryParseImmWithOptionalShift";
1132    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1133  }
1134}
1135// An ADD/SUB immediate shifter operand:
1136//  second operand:
1137//  {7-6} - shift type: 00 = lsl
1138//  {5-0} - imm6: #0 or #12
1139class addsub_shifted_imm<ValueType Ty>
1140    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1141  let PrintMethod = "printAddSubImm";
1142  let EncoderMethod = "getAddSubImmOpValue";
1143  let ParserMatchClass = AddSubImmOperand;
1144  let MIOperandInfo = (ops i32imm, i32imm);
1145}
1146
1147class addsub_shifted_imm_neg<ValueType Ty>
1148    : Operand<Ty> {
1149  let EncoderMethod = "getAddSubImmOpValue";
1150  let ParserMatchClass = AddSubImmNegOperand;
1151  let MIOperandInfo = (ops i32imm, i32imm);
1152}
1153
1154def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1155def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1156def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1157def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1158
1159def gi_addsub_shifted_imm32 :
1160    GIComplexOperandMatcher<s32, "selectArithImmed">,
1161    GIComplexPatternEquiv<addsub_shifted_imm32>;
1162
1163def gi_addsub_shifted_imm64 :
1164    GIComplexOperandMatcher<s64, "selectArithImmed">,
1165    GIComplexPatternEquiv<addsub_shifted_imm64>;
1166
1167class neg_addsub_shifted_imm<ValueType Ty>
1168    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1169  let PrintMethod = "printAddSubImm";
1170  let EncoderMethod = "getAddSubImmOpValue";
1171  let ParserMatchClass = AddSubImmOperand;
1172  let MIOperandInfo = (ops i32imm, i32imm);
1173}
1174
1175def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1176def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1177
1178def gi_neg_addsub_shifted_imm32 :
1179    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1180    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1181
1182def gi_neg_addsub_shifted_imm64 :
1183    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1184    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1185
1186// An extend operand:
1187//  {5-3} - extend type
1188//  {2-0} - imm3
1189def arith_extend : Operand<i32> {
1190  let PrintMethod = "printArithExtend";
1191  let ParserMatchClass = ExtendOperand;
1192}
1193def arith_extend64 : Operand<i32> {
1194  let PrintMethod = "printArithExtend";
1195  let ParserMatchClass = ExtendOperand64;
1196}
1197
1198// 'extend' that's a lsl of a 64-bit register.
1199def arith_extendlsl64 : Operand<i32> {
1200  let PrintMethod = "printArithExtend";
1201  let ParserMatchClass = ExtendOperandLSL64;
1202}
1203
1204class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1205                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1206  let PrintMethod = "printExtendedRegister";
1207  let MIOperandInfo = (ops GPR32, arith_extend);
1208}
1209
1210class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1211                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1212  let PrintMethod = "printExtendedRegister";
1213  let MIOperandInfo = (ops GPR32, arith_extend64);
1214}
1215
1216def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1217def gi_arith_extended_reg32_i32 :
1218    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1219    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1220
1221def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1222def gi_arith_extended_reg32_i64 :
1223    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1224    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1225
1226def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1227def gi_arith_extended_reg32to64_i64 :
1228    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1229    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1230
1231def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
1232
1233// Floating-point immediate.
1234
1235def fpimm16XForm : SDNodeXForm<fpimm, [{
1236      APFloat InVal = N->getValueAPF();
1237      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1238      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1239    }]>;
1240
1241def fpimm32XForm : SDNodeXForm<fpimm, [{
1242      APFloat InVal = N->getValueAPF();
1243      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1244      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1245    }]>;
1246
1247def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1248      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1249                                                          .bitcastToAPInt()
1250                                                          .getZExtValue());
1251      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1252    }]>;
1253
1254def fpimm64XForm : SDNodeXForm<fpimm, [{
1255      APFloat InVal = N->getValueAPF();
1256      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1257      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1258    }]>;
1259
1260def fpimm16 : Operand<f16>,
1261              FPImmLeaf<f16, [{
1262      return AArch64_AM::getFP16Imm(Imm) != -1;
1263    }], fpimm16XForm> {
1264  let ParserMatchClass = FPImmOperand;
1265  let PrintMethod = "printFPImmOperand";
1266}
1267
1268def fpimm32 : Operand<f32>,
1269              FPImmLeaf<f32, [{
1270      return AArch64_AM::getFP32Imm(Imm) != -1;
1271    }], fpimm32XForm> {
1272  let ParserMatchClass = FPImmOperand;
1273  let PrintMethod = "printFPImmOperand";
1274}
1275
1276def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1277      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1278      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1279    }], fpimm32SIMDModImmType4XForm> {
1280}
1281
1282def fpimm64 : Operand<f64>,
1283              FPImmLeaf<f64, [{
1284      return AArch64_AM::getFP64Imm(Imm) != -1;
1285    }], fpimm64XForm> {
1286  let ParserMatchClass = FPImmOperand;
1287  let PrintMethod = "printFPImmOperand";
1288}
1289
1290def fpimm8 : Operand<i32> {
1291  let ParserMatchClass = FPImmOperand;
1292  let PrintMethod = "printFPImmOperand";
1293}
1294
1295def fpimm0 : FPImmLeaf<fAny, [{
1296  return Imm.isExactlyValue(+0.0);
1297}]>;
1298
1299def fpimm_minus0 : FPImmLeaf<fAny, [{
1300  return Imm.isExactlyValue(-0.0);
1301}]>;
1302
1303def fpimm_half : FPImmLeaf<fAny, [{
1304  return Imm.isExactlyValue(+0.5);
1305}]>;
1306
1307def fpimm_one : FPImmLeaf<fAny, [{
1308  return Imm.isExactlyValue(+1.0);
1309}]>;
1310
1311def fpimm_two : FPImmLeaf<fAny, [{
1312  return Imm.isExactlyValue(+2.0);
1313}]>;
1314
1315def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1316  GISDNodeXFormEquiv<fpimm16XForm>;
1317def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1318  GISDNodeXFormEquiv<fpimm32XForm>;
1319def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1320  GISDNodeXFormEquiv<fpimm64XForm>;
1321def gi_fpimm32SIMDModImmType4 :
1322    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1323  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1324
1325// Vector lane operands
1326class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1327  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1328  let DiagnosticType = "Invalid" # Name;
1329  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1330  let RenderMethod = "addVectorIndexOperands";
1331}
1332
1333class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1334    : Operand<ty> {
1335  let ParserMatchClass = mc;
1336  let PrintMethod = "printVectorIndex";
1337}
1338
1339multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1340  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1341  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1342}
1343
1344def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1345def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1346def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1347def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1348def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1349def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1350
1351let OperandNamespace = "AArch64" in {
1352  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1353    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1354                                [{ return ((uint64_t)Imm) == 0; }]>;
1355  }
1356}
1357defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1358                                [{ return ((uint64_t)Imm) == 1; }]>;
1359defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1360                                [{ return ((uint64_t)Imm) < 16; }]>;
1361defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1362                                [{ return ((uint64_t)Imm) < 8; }]>;
1363defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1364                                [{ return ((uint64_t)Imm) < 4; }]>;
1365defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1366                                [{ return ((uint64_t)Imm) < 2; }]>;
1367
1368defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1369                                   [{ return ((uint64_t)Imm) == 1; }]>;
1370defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1371                                   [{ return ((uint64_t)Imm) < 16; }]>;
1372defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1373                                   [{ return ((uint64_t)Imm) < 8; }]>;
1374defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1375                                   [{ return ((uint64_t)Imm) < 4; }]>;
1376defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1377                                   [{ return ((uint64_t)Imm) < 2; }]>;
1378
1379def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1380def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1381def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1382def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1383def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1384
1385defm sve_elm_idx_extdup_b
1386  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1387                [{ return ((uint64_t)Imm) < 64; }]>;
1388defm sve_elm_idx_extdup_h
1389  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1390                [{ return ((uint64_t)Imm) < 32; }]>;
1391defm sve_elm_idx_extdup_s
1392  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1393                [{ return ((uint64_t)Imm) < 16; }]>;
1394defm sve_elm_idx_extdup_d
1395  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1396                [{ return ((uint64_t)Imm) < 8; }]>;
1397defm sve_elm_idx_extdup_q
1398  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1399                [{ return ((uint64_t)Imm) < 4; }]>;
1400
1401def sme_elm_idx0_0 : Operand<i32>, TImmLeaf<i32, [{
1402  return ((uint32_t)Imm) == 0;
1403}]> {
1404  let ParserMatchClass = Imm0_0Operand;
1405  let PrintMethod = "printMatrixIndex";
1406  let OperandNamespace = "AArch64";
1407  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1408}
1409def sme_elm_idx0_1 : Operand<i32>, TImmLeaf<i32, [{
1410  return ((uint32_t)Imm) <= 1;
1411}]> {
1412  let ParserMatchClass = Imm0_1Operand;
1413  let PrintMethod = "printMatrixIndex";
1414}
1415def sme_elm_idx0_3 : Operand<i32>, TImmLeaf<i32, [{
1416  return ((uint32_t)Imm) <= 3;
1417}]> {
1418  let ParserMatchClass = Imm0_3Operand;
1419  let PrintMethod = "printMatrixIndex";
1420}
1421def sme_elm_idx0_7 : Operand<i32>, TImmLeaf<i32, [{
1422  return ((uint32_t)Imm) <= 7;
1423}]> {
1424  let ParserMatchClass = Imm0_7Operand;
1425  let PrintMethod = "printMatrixIndex";
1426}
1427def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
1428  return ((uint32_t)Imm) <= 15;
1429}]> {
1430  let ParserMatchClass = Imm0_15Operand;
1431  let PrintMethod = "printMatrixIndex";
1432}
1433
1434// SME2 vector select offset operands
1435
1436// uimm3s8 predicate
1437// True if the immediate is a multiple of 8 in the range [0,56].
1438def UImm3s8Operand : UImmScaledMemoryIndexed<3, 8>;
1439
1440def uimm3s8 : Operand<i64>, ImmLeaf<i64,
1441[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
1442  let PrintMethod = "printVectorIndex<8>";
1443  let ParserMatchClass = UImm3s8Operand;
1444}
1445
1446class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
1447  let Name = "UImm" # Width # "s" # Scale # "Range";
1448  let DiagnosticType = "InvalidMemoryIndexedRange" # Scale # "UImm" # Width;
1449  let RenderMethod = "addImmScaledRangeOperands<" # Scale # ">";
1450  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ", " # OffsetVal # ", /*IsRange=*/true>";
1451  let ParserMethod = "tryParseImmRange";
1452}
1453
1454// Implicit immediate ranges 0:1 and 0:3, scale has no meaning
1455// since the immediate is zero
1456def UImm0s2RangeOperand : UImmScaledMemoryIndexedRange<0, 2, 1>;
1457def UImm0s4RangeOperand : UImmScaledMemoryIndexedRange<0, 4, 3>;
1458
1459def UImm1s2RangeOperand : UImmScaledMemoryIndexedRange<1, 2, 1>;
1460def UImm1s4RangeOperand : UImmScaledMemoryIndexedRange<1, 4, 3>;
1461def UImm2s2RangeOperand : UImmScaledMemoryIndexedRange<2, 2, 1>;
1462def UImm2s4RangeOperand : UImmScaledMemoryIndexedRange<2, 4, 3>;
1463def UImm3s2RangeOperand : UImmScaledMemoryIndexedRange<3, 2, 1>;
1464
1465def uimm0s2range : Operand<i64>, ImmLeaf<i64,
1466[{ return Imm == 0; }], UImmS1XForm> {
1467  let PrintMethod = "printImmRangeScale<2, 1>";
1468  let ParserMatchClass = UImm0s2RangeOperand;
1469  let OperandNamespace = "AArch64";
1470  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1471}
1472
1473def uimm0s4range : Operand<i64>, ImmLeaf<i64,
1474[{ return Imm == 0; }], UImmS1XForm> {
1475  let PrintMethod = "printImmRangeScale<4, 3>";
1476  let ParserMatchClass = UImm0s4RangeOperand;
1477  let OperandNamespace = "AArch64";
1478  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1479}
1480
1481def uimm1s2range : Operand<i64>, ImmLeaf<i64,
1482[{ return Imm >= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> {
1483  let PrintMethod = "printImmRangeScale<2, 1>";
1484  let ParserMatchClass = UImm1s2RangeOperand;
1485}
1486
1487def uimm1s4range : Operand<i64>, ImmLeaf<i64,
1488[{ return Imm >= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> {
1489  let PrintMethod = "printImmRangeScale<4, 3>";
1490  let ParserMatchClass = UImm1s4RangeOperand;
1491}
1492
1493def uimm2s2range : Operand<i64>, ImmLeaf<i64,
1494[{ return Imm >= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> {
1495  let PrintMethod = "printImmRangeScale<2, 1>";
1496  let ParserMatchClass = UImm2s2RangeOperand;
1497}
1498
1499def uimm2s4range : Operand<i64>, ImmLeaf<i64,
1500[{ return Imm >= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> {
1501  let PrintMethod = "printImmRangeScale<4, 3>";
1502  let ParserMatchClass = UImm2s4RangeOperand;
1503}
1504
1505def uimm3s2range : Operand<i64>, ImmLeaf<i64,
1506[{ return Imm >= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> {
1507  let PrintMethod = "printImmRangeScale<2, 1>";
1508  let ParserMatchClass = UImm3s2RangeOperand;
1509}
1510
1511
1512// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1513// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1514// are encoded as the eight bit value 'abcdefgh'.
1515def simdimmtype10 : Operand<i32>,
1516                    FPImmLeaf<f64, [{
1517      return AArch64_AM::isAdvSIMDModImmType10(
1518                 Imm.bitcastToAPInt().getZExtValue());
1519    }], SDNodeXForm<fpimm, [{
1520      APFloat InVal = N->getValueAPF();
1521      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1522                                                           .bitcastToAPInt()
1523                                                           .getZExtValue());
1524      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1525    }]>> {
1526  let ParserMatchClass = SIMDImmType10Operand;
1527  let PrintMethod = "printSIMDType10Operand";
1528}
1529
1530
1531//---
1532// System management
1533//---
1534
1535// Base encoding for system instruction operands.
1536let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1537class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1538                  list<dag> pattern = []>
1539    : I<oops, iops, asm, operands, "", pattern> {
1540  let Inst{31-22} = 0b1101010100;
1541  let Inst{21}    = L;
1542}
1543
1544// System instructions which do not have an Rt register.
1545class SimpleSystemI<bit L, dag iops, string asm, string operands,
1546                    list<dag> pattern = []>
1547    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1548  let Inst{4-0} = 0b11111;
1549}
1550
1551// System instructions which have an Rt register.
1552class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1553                list<dag> pattern = []>
1554    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1555      Sched<[WriteSys]> {
1556  bits<5> Rt;
1557  let Inst{4-0} = Rt;
1558}
1559
1560// System instructions for transactional memory extension
1561class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1562                    string asm, string operands, list<dag> pattern>
1563    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1564      Sched<[WriteSys]> {
1565  let Inst{20-12} = 0b000110011;
1566  let Inst{11-8} = CRm;
1567  let Inst{7-5} = op2;
1568  let DecoderMethod = "";
1569
1570  let mayLoad = 1;
1571  let mayStore = 1;
1572}
1573
1574// System instructions for transactional memory - single input operand
1575class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1576    : TMBaseSystemI<0b1, CRm, 0b011,
1577                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1578  bits<5> Rt;
1579  let Inst{4-0} = Rt;
1580}
1581
1582// System instructions that pass a register argument
1583// This class assumes the register is for input rather than output.
1584class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1585                      list<dag> pattern = []>
1586    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1587  let Inst{20-12} = 0b000110001;
1588  let Inst{11-8} = CRm;
1589  let Inst{7-5} = Op2;
1590}
1591
1592// System instructions for transactional memory - no operand
1593class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1594    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1595  let Inst{4-0} = 0b11111;
1596}
1597
1598// System instructions for exit from transactions
1599class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1600    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1601      Sched<[WriteSys]> {
1602  bits<16> imm;
1603  let Inst{31-24} = 0b11010100;
1604  let Inst{23-21} = op1;
1605  let Inst{20-5}  = imm;
1606  let Inst{4-0}   = 0b00000;
1607}
1608
1609// Hint instructions that take both a CRm and a 3-bit immediate.
1610// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1611// model patterns with sufficiently fine granularity
1612let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1613  class HintI<string mnemonic>
1614      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1615                      [(int_aarch64_hint imm0_127:$imm)]>,
1616        Sched<[WriteHint]> {
1617    bits <7> imm;
1618    let Inst{20-12} = 0b000110010;
1619    let Inst{11-5} = imm;
1620  }
1621
1622// System instructions taking a single literal operand which encodes into
1623// CRm. op2 differentiates the opcodes.
1624def BarrierAsmOperand : AsmOperandClass {
1625  let Name = "Barrier";
1626  let ParserMethod = "tryParseBarrierOperand";
1627}
1628def barrier_op : Operand<i32> {
1629  let PrintMethod = "printBarrierOption";
1630  let ParserMatchClass = BarrierAsmOperand;
1631}
1632def BarriernXSAsmOperand : AsmOperandClass {
1633  let Name = "BarriernXS";
1634  let ParserMethod = "tryParseBarriernXSOperand";
1635}
1636def barrier_nxs_op : Operand<i32> {
1637  let PrintMethod = "printBarriernXSOption";
1638  let ParserMatchClass = BarriernXSAsmOperand;
1639}
1640class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1641                 list<dag> pattern = []>
1642    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1643      Sched<[WriteBarrier]> {
1644  bits<4> CRm;
1645  let Inst{20-12} = 0b000110011;
1646  let Inst{11-8} = CRm;
1647  let Inst{7-5} = opc;
1648}
1649
1650class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1651    : SimpleSystemI<0, (ins), asm, "", pattern>,
1652      Sched<[WriteHint]> {
1653  bits<4> CRm;
1654  let CRm = 0b0011;
1655  let Inst{31-12} = 0b11010101000000110010;
1656  let Inst{11-8} = CRm;
1657  let Inst{7-5} = op2;
1658  let Inst{4-0} = 0b11111;
1659}
1660
1661// MRS/MSR system instructions. These have different operand classes because
1662// a different subset of registers can be accessed through each instruction.
1663def MRSSystemRegisterOperand : AsmOperandClass {
1664  let Name = "MRSSystemRegister";
1665  let ParserMethod = "tryParseSysReg";
1666  let DiagnosticType = "MRS";
1667}
1668// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1669def mrs_sysreg_op : Operand<i32> {
1670  let ParserMatchClass = MRSSystemRegisterOperand;
1671  let DecoderMethod = "DecodeMRSSystemRegister";
1672  let PrintMethod = "printMRSSystemRegister";
1673}
1674
1675def MSRSystemRegisterOperand : AsmOperandClass {
1676  let Name = "MSRSystemRegister";
1677  let ParserMethod = "tryParseSysReg";
1678  let DiagnosticType = "MSR";
1679}
1680def msr_sysreg_op : Operand<i32> {
1681  let ParserMatchClass = MSRSystemRegisterOperand;
1682  let DecoderMethod = "DecodeMSRSystemRegister";
1683  let PrintMethod = "printMSRSystemRegister";
1684}
1685
1686def PSBHintOperand : AsmOperandClass {
1687  let Name = "PSBHint";
1688  let ParserMethod = "tryParsePSBHint";
1689}
1690def psbhint_op : Operand<i32> {
1691  let ParserMatchClass = PSBHintOperand;
1692  let PrintMethod = "printPSBHintOp";
1693  let MCOperandPredicate = [{
1694    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1695    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1696    if (!MCOp.isImm())
1697      return false;
1698    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1699  }];
1700}
1701
1702def BTIHintOperand : AsmOperandClass {
1703  let Name = "BTIHint";
1704  let ParserMethod = "tryParseBTIHint";
1705}
1706def btihint_op : Operand<i32> {
1707  let ParserMatchClass = BTIHintOperand;
1708  let PrintMethod = "printBTIHintOp";
1709  let MCOperandPredicate = [{
1710    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1711    if (!MCOp.isImm())
1712      return false;
1713    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1714  }];
1715}
1716
1717class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1718                       "mrs", "\t$Rt, $systemreg"> {
1719  bits<16> systemreg;
1720  let Inst{20-5} = systemreg;
1721  let DecoderNamespace = "Fallback";
1722  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1723  // require doing this. The alternative was to explicitly model each one, but
1724  // it feels like it is unnecessary because it seems there are no negative
1725  // consequences setting these flags for all.
1726  let Defs = [NZCV];
1727}
1728
1729// FIXME: Some of these def NZCV, others don't. Best way to model that?
1730// Explicitly modeling each of the system register as a register class
1731// would do it, but feels like overkill at this point.
1732class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1733                       "msr", "\t$systemreg, $Rt"> {
1734  bits<16> systemreg;
1735  let Inst{20-5} = systemreg;
1736  let DecoderNamespace = "Fallback";
1737}
1738
1739def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1740  let Name = "SystemPStateFieldWithImm0_15";
1741  let ParserMethod = "tryParseSysReg";
1742}
1743def pstatefield4_op : Operand<i32> {
1744  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1745  let PrintMethod = "printSystemPStateField";
1746  let MCOperandPredicate = [{
1747    if (!MCOp.isImm())
1748      return false;
1749    return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr;
1750  }];
1751}
1752
1753// Instructions to modify PSTATE, no input reg
1754let Defs = [NZCV] in
1755class PstateWriteSimple<dag iops, string asm, string operands>
1756  : SimpleSystemI<0, iops, asm, operands> {
1757
1758  let Inst{20-19} = 0b00;
1759  let Inst{15-12} = 0b0100;
1760}
1761
1762class MSRpstateImm0_15
1763  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1764                  "\t$pstatefield, $imm">,
1765    Sched<[WriteSys]> {
1766
1767  bits<6> pstatefield;
1768  bits<4> imm;
1769  let Inst{18-16} = pstatefield{5-3};
1770  let Inst{11-8} = imm;
1771  let Inst{7-5} = pstatefield{2-0};
1772
1773  let DecoderMethod = "DecodeSystemPStateImm0_15Instruction";
1774  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1775  // Fail the decoder should attempt to decode the instruction as MSRI.
1776  let hasCompleteDecoder = false;
1777}
1778
1779def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1780  let Name = "SystemPStateFieldWithImm0_1";
1781  let ParserMethod = "tryParseSysReg";
1782}
1783def pstatefield1_op : Operand<i32> {
1784  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1785  let PrintMethod = "printSystemPStateField";
1786  let MCOperandPredicate = [{
1787    if (!MCOp.isImm())
1788      return false;
1789    return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr;
1790  }];
1791}
1792
1793class MSRpstateImm0_1
1794  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1795                 "\t$pstatefield, $imm">,
1796    Sched<[WriteSys]> {
1797
1798  bits<9> pstatefield;
1799  bit imm;
1800  let Inst{18-16} = pstatefield{5-3};
1801  let Inst{11-9} = pstatefield{8-6};
1802  let Inst{8} = imm;
1803  let Inst{7-5} = pstatefield{2-0};
1804
1805  let DecoderMethod = "DecodeSystemPStateImm0_1Instruction";
1806  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1807  // Fail the decoder should attempt to decode the instruction as MSRI.
1808  let hasCompleteDecoder = false;
1809  let DecoderNamespace = "Fallback";
1810}
1811
1812// SYS and SYSL generic system instructions.
1813def SysCRAsmOperand : AsmOperandClass {
1814  let Name = "SysCR";
1815  let ParserMethod = "tryParseSysCROperand";
1816}
1817
1818def sys_cr_op : Operand<i32> {
1819  let PrintMethod = "printSysCROperand";
1820  let ParserMatchClass = SysCRAsmOperand;
1821}
1822
1823class SystemXtI<bit L, string asm>
1824  : RtSystemI<L, (outs),
1825       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1826       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1827  bits<3> op1;
1828  bits<4> Cn;
1829  bits<4> Cm;
1830  bits<3> op2;
1831  let Inst{20-19} = 0b01;
1832  let Inst{18-16} = op1;
1833  let Inst{15-12} = Cn;
1834  let Inst{11-8}  = Cm;
1835  let Inst{7-5}   = op2;
1836}
1837
1838class SystemLXtI<bit L, string asm>
1839  : RtSystemI<L, (outs),
1840       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1841       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1842  bits<3> op1;
1843  bits<4> Cn;
1844  bits<4> Cm;
1845  bits<3> op2;
1846  let Inst{20-19} = 0b01;
1847  let Inst{18-16} = op1;
1848  let Inst{15-12} = Cn;
1849  let Inst{11-8}  = Cm;
1850  let Inst{7-5}   = op2;
1851}
1852
1853def RangePrefetchOperand : AsmOperandClass {
1854  let Name = "RangePrefetch";
1855  let ParserMethod = "tryParseRPRFMOperand";
1856  let PredicateMethod = "isPrefetch";
1857  let RenderMethod = "addPrefetchOperands";
1858}
1859
1860def rprfop : Operand<i32>, TImmLeaf<i32, [{
1861    return (((uint32_t)Imm) <= 63);
1862  }]> {
1863  let PrintMethod = "printRPRFMOperand";
1864  let ParserMatchClass = RangePrefetchOperand;
1865}
1866
1867// Branch (register) instructions:
1868//
1869//  case opc of
1870//    0001 blr
1871//    0000 br
1872//    0101 dret
1873//    0100 eret
1874//    0010 ret
1875//    otherwise UNDEFINED
1876class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1877                    string operands, list<dag> pattern>
1878    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1879  let Inst{31-25} = 0b1101011;
1880  let Inst{24-21} = opc;
1881  let Inst{20-16} = 0b11111;
1882  let Inst{15-10} = 0b000000;
1883  let Inst{4-0}   = 0b00000;
1884}
1885
1886class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1887    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1888  bits<5> Rn;
1889  let Inst{9-5} = Rn;
1890}
1891
1892let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1893class SpecialReturn<bits<4> opc, string asm>
1894    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1895  let Inst{9-5} = 0b11111;
1896}
1897
1898let mayLoad = 1 in
1899class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1900  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1901  Sched<[]> {
1902  bits<5> Rn;
1903  bits<5> Rt;
1904  let Inst{31-30} = sz;
1905  let Inst{29-10} = 0b11100010111111110000;
1906  let Inst{9-5} = Rn;
1907  let Inst{4-0} = Rt;
1908}
1909
1910class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1911               list<dag> pattern>
1912  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1913  let isAuthenticated = 1;
1914  let Inst{31-25} = 0b1101011;
1915  let Inst{20-11} = 0b1111100001;
1916  let Inst{10} = M;
1917  let Inst{4-0} = 0b11111;
1918}
1919
1920class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1921  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1922  bits<5> Rn;
1923  bits<5> Rm;
1924  let Inst{24-22} = 0b100;
1925  let Inst{21} = op;
1926  let Inst{9-5} = Rn;
1927  let Inst{4-0} = Rm;
1928}
1929
1930class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1931  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1932  bits<5> Rn;
1933  let Inst{24} = 0;
1934  let Inst{23-21} = opc;
1935  let Inst{9-5} = Rn;
1936}
1937
1938let Uses = [LR,SP] in
1939class AuthReturn<bits<3> op, bits<1> M, string asm>
1940  : AuthBase<M, (outs), (ins), asm, "", []> {
1941  let Inst{24} = 0;
1942  let Inst{23-21} = op;
1943  let Inst{9-0} = 0b1111111111;
1944}
1945
1946let mayLoad = 1 in
1947class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1948                   string operands, string cstr>
1949  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1950  bits<10> offset;
1951  bits<5> Rn;
1952  bits<5> Rt;
1953  let isAuthenticated = 1;
1954  let Inst{31-24} = 0b11111000;
1955  let Inst{23} = M;
1956  let Inst{22} = offset{9};
1957  let Inst{21} = 1;
1958  let Inst{20-12} = offset{8-0};
1959  let Inst{11} = W;
1960  let Inst{10} = 1;
1961  let Inst{9-5} = Rn;
1962  let Inst{4-0} = Rt;
1963
1964  let DecoderMethod = "DecodeAuthLoadInstruction";
1965}
1966
1967multiclass AuthLoad<bit M, string asm, Operand opr> {
1968  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1969                               (ins GPR64sp:$Rn, opr:$offset),
1970                               asm, "\t$Rt, [$Rn, $offset]", "">;
1971  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1972                               (ins GPR64sp:$Rn, opr:$offset),
1973                               asm, "\t$Rt, [$Rn, $offset]!",
1974                               "$Rn = $wback,@earlyclobber $wback">;
1975
1976  def : InstAlias<asm # "\t$Rt, [$Rn]",
1977                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1978
1979  def : InstAlias<asm # "\t$Rt, [$wback]!",
1980                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1981}
1982
1983//---
1984// Conditional branch instruction.
1985//---
1986
1987// Condition code.
1988// 4-bit immediate. Pretty-printed as <cc>
1989def ccode : Operand<i32> {
1990  let PrintMethod = "printCondCode";
1991  let ParserMatchClass = CondCode;
1992}
1993def inv_ccode : Operand<i32> {
1994  // AL and NV are invalid in the aliases which use inv_ccode
1995  let PrintMethod = "printInverseCondCode";
1996  let ParserMatchClass = CondCode;
1997  let MCOperandPredicate = [{
1998    return MCOp.isImm() &&
1999           MCOp.getImm() != AArch64CC::AL &&
2000           MCOp.getImm() != AArch64CC::NV;
2001  }];
2002}
2003
2004// Conditional branch target. 19-bit immediate. The low two bits of the target
2005// offset are implied zero and so are not part of the immediate.
2006def am_brcond : Operand<OtherVT> {
2007  let EncoderMethod = "getCondBranchTargetOpValue";
2008  let DecoderMethod = "DecodePCRelLabel19";
2009  let PrintMethod = "printAlignedLabel";
2010  let ParserMatchClass = PCRelLabel19Operand;
2011  let OperandType = "OPERAND_PCREL";
2012}
2013
2014class BranchCond<bit bit4, string mnemonic>
2015   : I<(outs), (ins ccode:$cond, am_brcond:$target),
2016       mnemonic, ".$cond\t$target", "",
2017       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
2018  let isBranch = 1;
2019  let isTerminator = 1;
2020  let Uses = [NZCV];
2021
2022  bits<4> cond;
2023  bits<19> target;
2024  let Inst{31-24} = 0b01010100;
2025  let Inst{23-5} = target;
2026  let Inst{4} = bit4;
2027  let Inst{3-0} = cond;
2028}
2029
2030//---
2031// Compare-and-branch instructions.
2032//---
2033class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
2034    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
2035         asm, "\t$Rt, $target", "",
2036         [(node regtype:$Rt, bb:$target)]>,
2037      Sched<[WriteBr]> {
2038  let isBranch = 1;
2039  let isTerminator = 1;
2040
2041  bits<5> Rt;
2042  bits<19> target;
2043  let Inst{30-25} = 0b011010;
2044  let Inst{24}    = op;
2045  let Inst{23-5}  = target;
2046  let Inst{4-0}   = Rt;
2047}
2048
2049multiclass CmpBranch<bit op, string asm, SDNode node> {
2050  def W : BaseCmpBranch<GPR32, op, asm, node> {
2051    let Inst{31} = 0;
2052  }
2053  def X : BaseCmpBranch<GPR64, op, asm, node> {
2054    let Inst{31} = 1;
2055  }
2056}
2057
2058//---
2059// Test-bit-and-branch instructions.
2060//---
2061// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
2062// the target offset are implied zero and so are not part of the immediate.
2063def am_tbrcond : Operand<OtherVT> {
2064  let EncoderMethod = "getTestBranchTargetOpValue";
2065  let PrintMethod = "printAlignedLabel";
2066  let ParserMatchClass = BranchTarget14Operand;
2067  let OperandType = "OPERAND_PCREL";
2068}
2069
2070// AsmOperand classes to emit (or not) special diagnostics
2071def TBZImm0_31Operand : AsmOperandClass {
2072  let Name = "TBZImm0_31";
2073  let PredicateMethod = "isImmInRange<0,31>";
2074  let RenderMethod = "addImmOperands";
2075}
2076def TBZImm32_63Operand : AsmOperandClass {
2077  let Name = "Imm32_63";
2078  let PredicateMethod = "isImmInRange<32,63>";
2079  let DiagnosticType = "InvalidImm0_63";
2080  let RenderMethod = "addImmOperands";
2081}
2082
2083class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
2084  return (((uint32_t)Imm) < 32);
2085}]> {
2086  let ParserMatchClass = matcher;
2087}
2088
2089def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
2090def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
2091
2092def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
2093  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
2094}]> {
2095  let ParserMatchClass = TBZImm32_63Operand;
2096}
2097
2098class BaseTestBranch<RegisterClass regtype, Operand immtype,
2099                     bit op, string asm, SDNode node>
2100    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
2101       asm, "\t$Rt, $bit_off, $target", "",
2102       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
2103      Sched<[WriteBr]> {
2104  let isBranch = 1;
2105  let isTerminator = 1;
2106
2107  bits<5> Rt;
2108  bits<6> bit_off;
2109  bits<14> target;
2110
2111  let Inst{30-25} = 0b011011;
2112  let Inst{24}    = op;
2113  let Inst{23-19} = bit_off{4-0};
2114  let Inst{18-5}  = target;
2115  let Inst{4-0}   = Rt;
2116
2117  let DecoderMethod = "DecodeTestAndBranch";
2118}
2119
2120multiclass TestBranch<bit op, string asm, SDNode node> {
2121  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
2122    let Inst{31} = 0;
2123  }
2124
2125  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
2126    let Inst{31} = 1;
2127  }
2128
2129  // Alias X-reg with 0-31 imm to W-Reg.
2130  def : InstAlias<asm # "\t$Rd, $imm, $target",
2131                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
2132                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
2133  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
2134            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
2135            tbz_imm0_31_diag:$imm, bb:$target)>;
2136}
2137
2138//---
2139// Unconditional branch (immediate) instructions.
2140//---
2141def am_b_target : Operand<OtherVT> {
2142  let EncoderMethod = "getBranchTargetOpValue";
2143  let PrintMethod = "printAlignedLabel";
2144  let ParserMatchClass = BranchTarget26Operand;
2145  let OperandType = "OPERAND_PCREL";
2146}
2147def am_bl_target : Operand<i64> {
2148  let EncoderMethod = "getBranchTargetOpValue";
2149  let PrintMethod = "printAlignedLabel";
2150  let ParserMatchClass = BranchTarget26Operand;
2151  let OperandType = "OPERAND_PCREL";
2152}
2153
2154class BImm<bit op, dag iops, string asm, list<dag> pattern>
2155    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
2156  bits<26> addr;
2157  let Inst{31}    = op;
2158  let Inst{30-26} = 0b00101;
2159  let Inst{25-0}  = addr;
2160
2161  let DecoderMethod = "DecodeUnconditionalBranch";
2162}
2163
2164class BranchImm<bit op, string asm, list<dag> pattern>
2165    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2166class CallImm<bit op, string asm, list<dag> pattern>
2167    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2168
2169//---
2170// Basic one-operand data processing instructions.
2171//---
2172
2173let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2174class BaseOneOperandData<bit sf, bit S, bits<5> opc2, bits<6> opc,
2175                         RegisterClass regtype, string asm,
2176                         SDPatternOperator node>
2177  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2178      [(set regtype:$Rd, (node regtype:$Rn))]>,
2179    Sched<[WriteI, ReadI]> {
2180  bits<5> Rd;
2181  bits<5> Rn;
2182
2183  let Inst{31} = sf;
2184  let Inst{30} = 0b1;
2185  let Inst{29} = S;
2186  let Inst{28-21} = 0b11010110;
2187  let Inst{20-16} = opc2;
2188  let Inst{15-10} = opc;
2189  let Inst{9-5}   = Rn;
2190  let Inst{4-0}   = Rd;
2191}
2192
2193let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2194multiclass OneOperandData<bits<6> opc, string asm,
2195                          SDPatternOperator node = null_frag> {
2196  def Wr : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2197
2198  def Xr : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2199}
2200
2201class OneWRegData<bits<6> opc, string asm, SDPatternOperator node>
2202    : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2203
2204class OneXRegData<bits<6> opc, string asm, SDPatternOperator node>
2205    : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2206
2207class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2208                      SDPatternOperator op>
2209  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2210      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2211    Sched<[WriteI, ReadI]> {
2212  bits<5> Rd;
2213  bits<5> Rn;
2214  let Inst{31-15} = 0b11011010110000010;
2215  let Inst{14-12} = opcode_prefix;
2216  let Inst{11-10} = opcode;
2217  let Inst{9-5} = Rn;
2218  let Inst{4-0} = Rd;
2219}
2220
2221class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2222                   SDPatternOperator op>
2223  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2224      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2225    Sched<[]> {
2226  bits<5> Rd;
2227  let Inst{31-15} = 0b11011010110000010;
2228  let Inst{14-12} = opcode_prefix;
2229  let Inst{11-10} = opcode;
2230  let Inst{9-5} = 0b11111;
2231  let Inst{4-0} = Rd;
2232}
2233
2234class SignAuthTwoOperand<bits<4> opc, string asm,
2235                         SDPatternOperator OpNode>
2236  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2237      asm, "\t$Rd, $Rn, $Rm", "",
2238      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2239    Sched<[WriteI, ReadI, ReadI]> {
2240  bits<5> Rd;
2241  bits<5> Rn;
2242  bits<5> Rm;
2243  let Inst{31-21} = 0b10011010110;
2244  let Inst{20-16} = Rm;
2245  let Inst{15-14} = 0b00;
2246  let Inst{13-10} = opc;
2247  let Inst{9-5}   = Rn;
2248  let Inst{4-0}   = Rd;
2249}
2250
2251class ClearAuth<bits<1> data, string asm>
2252  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2253  bits<5> Rd;
2254  let Inst{31-11} = 0b110110101100000101000;
2255  let Inst{10} = data;
2256  let Inst{9-5} = 0b11111;
2257  let Inst{4-0} = Rd;
2258}
2259
2260// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2261class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2262    : I<(outs), iops, asm, ops, "", []>,
2263      Sched<[WriteI, ReadI, ReadI]> {
2264  let Uses = [NZCV];
2265  let Defs = [NZCV];
2266  bits<5> Rn;
2267  let Inst{31}    = sf;
2268  let Inst{30-15} = 0b0111010000000000;
2269  let Inst{14}    = sz;
2270  let Inst{13-10} = 0b0010;
2271  let Inst{9-5}   = Rn;
2272  let Inst{4-0}   = 0b01101;
2273}
2274
2275class FlagRotate<dag iops, string asm, string ops>
2276    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2277  bits<6> imm;
2278  bits<4> mask;
2279  let Inst{20-15} = imm;
2280  let Inst{13-10} = 0b0001;
2281  let Inst{4}     = 0b0;
2282  let Inst{3-0}   = mask;
2283}
2284
2285//---
2286// Basic two-operand data processing instructions.
2287//---
2288class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2289                          list<dag> pattern>
2290    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2291        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2292      Sched<[WriteI, ReadI, ReadI]> {
2293  let Uses = [NZCV];
2294  bits<5> Rd;
2295  bits<5> Rn;
2296  bits<5> Rm;
2297  let Inst{30}    = isSub;
2298  let Inst{28-21} = 0b11010000;
2299  let Inst{20-16} = Rm;
2300  let Inst{15-10} = 0;
2301  let Inst{9-5}   = Rn;
2302  let Inst{4-0}   = Rd;
2303}
2304
2305class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2306                      SDNode OpNode>
2307    : BaseBaseAddSubCarry<isSub, regtype, asm,
2308        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2309
2310class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2311                              SDNode OpNode>
2312    : BaseBaseAddSubCarry<isSub, regtype, asm,
2313        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2314         (implicit NZCV)]> {
2315  let Defs = [NZCV];
2316}
2317
2318multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2319                       SDNode OpNode, SDNode OpNode_setflags> {
2320  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2321    let Inst{31} = 0;
2322    let Inst{29} = 0;
2323  }
2324  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2325    let Inst{31} = 1;
2326    let Inst{29} = 0;
2327  }
2328
2329  // Sets flags.
2330  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2331                                    OpNode_setflags> {
2332    let Inst{31} = 0;
2333    let Inst{29} = 1;
2334  }
2335  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2336                                    OpNode_setflags> {
2337    let Inst{31} = 1;
2338    let Inst{29} = 1;
2339  }
2340}
2341
2342class BaseTwoOperandRegReg<bit sf, bit S, bits<6> opc, RegisterClass regtype,
2343                           string asm, SDPatternOperator OpNode,
2344                           RegisterClass in1regtype = regtype,
2345                           RegisterClass in2regtype = regtype>
2346  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2347      asm, "\t$Rd, $Rn, $Rm", "",
2348      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2349  bits<5> Rd;
2350  bits<5> Rn;
2351  bits<5> Rm;
2352  let Inst{31}    = sf;
2353  let Inst{30}    = 0b0;
2354  let Inst{29}    = S;
2355  let Inst{28-21} = 0b11010110;
2356  let Inst{20-16} = Rm;
2357  let Inst{15-10} = opc;
2358  let Inst{9-5}   = Rn;
2359  let Inst{4-0}   = Rd;
2360}
2361
2362class BaseDiv<bit size, bit isSigned, RegisterClass regtype, string asm,
2363              SDPatternOperator OpNode>
2364    : BaseTwoOperandRegReg<size, 0b0, {0,0,0,0,1,?}, regtype, asm, OpNode> {
2365  let Inst{10}    = isSigned;
2366}
2367
2368multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2369  def Wr : BaseDiv<0b0, isSigned, GPR32, asm, OpNode>,
2370           Sched<[WriteID32, ReadID, ReadID]>;
2371
2372  def Xr : BaseDiv<0b1, isSigned, GPR64, asm, OpNode>,
2373           Sched<[WriteID64, ReadID, ReadID]>;
2374}
2375
2376class BaseShift<bit size, bits<2> shift_type, RegisterClass regtype, string asm,
2377                SDPatternOperator OpNode = null_frag>
2378  : BaseTwoOperandRegReg<size, 0b0, {0,0,1,0,?,?}, regtype, asm, OpNode>,
2379    Sched<[WriteIS, ReadI]> {
2380  let Inst{11-10} = shift_type;
2381}
2382
2383multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2384  def Wr : BaseShift<0b0, shift_type, GPR32, asm>;
2385
2386  def Xr : BaseShift<0b1, shift_type, GPR64, asm, OpNode>;
2387
2388  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2389            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2390                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2391
2392  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2393            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2394
2395  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2396            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2397
2398  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2399            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2400
2401  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2402            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2403                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2404
2405  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2406            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2407                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2408}
2409
2410class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2411    : InstAlias<asm#"\t$dst, $src1, $src2",
2412                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2413
2414class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2415                       RegisterClass addtype, string asm,
2416                       list<dag> pattern>
2417  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2418      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2419  bits<5> Rd;
2420  bits<5> Rn;
2421  bits<5> Rm;
2422  bits<5> Ra;
2423  let Inst{30-24} = 0b0011011;
2424  let Inst{23-21} = opc;
2425  let Inst{20-16} = Rm;
2426  let Inst{15}    = isSub;
2427  let Inst{14-10} = Ra;
2428  let Inst{9-5}   = Rn;
2429  let Inst{4-0}   = Rd;
2430}
2431
2432multiclass MulAccum<bit isSub, string asm> {
2433  // MADD/MSUB generation is decided by MachineCombiner.cpp
2434  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2435      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2436    let Inst{31} = 0;
2437  }
2438
2439  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2440      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2441    let Inst{31} = 1;
2442  }
2443}
2444
2445class WideMulAccum<bit isSub, bits<3> opc, string asm,
2446                   SDNode AccNode, SDNode ExtNode>
2447  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2448    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2449                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2450    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2451  let Inst{31} = 1;
2452}
2453
2454class MulHi<bits<3> opc, string asm, SDNode OpNode>
2455  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2456      asm, "\t$Rd, $Rn, $Rm", "",
2457      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2458    Sched<[WriteIM64, ReadIM, ReadIM]> {
2459  bits<5> Rd;
2460  bits<5> Rn;
2461  bits<5> Rm;
2462  let Inst{31-24} = 0b10011011;
2463  let Inst{23-21} = opc;
2464  let Inst{20-16} = Rm;
2465  let Inst{15}    = 0;
2466  let Inst{9-5}   = Rn;
2467  let Inst{4-0}   = Rd;
2468
2469  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2470  // (i.e. all bits 1) but is ignored by the processor.
2471  let PostEncoderMethod = "fixMulHigh";
2472}
2473
2474class MulAccumWAlias<string asm, Instruction inst>
2475    : InstAlias<asm#"\t$dst, $src1, $src2",
2476                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2477class MulAccumXAlias<string asm, Instruction inst>
2478    : InstAlias<asm#"\t$dst, $src1, $src2",
2479                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2480class WideMulAccumAlias<string asm, Instruction inst>
2481    : InstAlias<asm#"\t$dst, $src1, $src2",
2482                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2483
2484class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2485              SDPatternOperator OpNode, string asm>
2486  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2487      asm, "\t$Rd, $Rn, $Rm", "",
2488      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2489    Sched<[WriteISReg, ReadI, ReadISReg]> {
2490  bits<5> Rd;
2491  bits<5> Rn;
2492  bits<5> Rm;
2493
2494  let Inst{31} = sf;
2495  let Inst{30-21} = 0b0011010110;
2496  let Inst{20-16} = Rm;
2497  let Inst{15-13} = 0b010;
2498  let Inst{12} = C;
2499  let Inst{11-10} = sz;
2500  let Inst{9-5} = Rn;
2501  let Inst{4-0} = Rd;
2502  let Predicates = [HasCRC];
2503}
2504
2505//---
2506// Address generation.
2507//---
2508
2509class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2510    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2511        pattern>,
2512      Sched<[WriteI]> {
2513  bits<5>  Xd;
2514  bits<21> label;
2515  let Inst{31}    = page;
2516  let Inst{30-29} = label{1-0};
2517  let Inst{28-24} = 0b10000;
2518  let Inst{23-5}  = label{20-2};
2519  let Inst{4-0}   = Xd;
2520
2521  let DecoderMethod = "DecodeAdrInstruction";
2522}
2523
2524//---
2525// Move immediate.
2526//---
2527
2528def movimm32_imm : Operand<i32> {
2529  let ParserMatchClass = AsmImmRange<0, 65535>;
2530  let EncoderMethod = "getMoveWideImmOpValue";
2531  let PrintMethod = "printImm";
2532}
2533def movimm32_shift : Operand<i32> {
2534  let PrintMethod = "printShifter";
2535  let ParserMatchClass = MovImm32ShifterOperand;
2536}
2537def movimm64_shift : Operand<i32> {
2538  let PrintMethod = "printShifter";
2539  let ParserMatchClass = MovImm64ShifterOperand;
2540}
2541
2542let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2543class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2544                        string asm>
2545  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2546       asm, "\t$Rd, $imm$shift", "", []>,
2547    Sched<[WriteImm]> {
2548  bits<5> Rd;
2549  bits<16> imm;
2550  bits<6> shift;
2551  let Inst{30-29} = opc;
2552  let Inst{28-23} = 0b100101;
2553  let Inst{22-21} = shift{5-4};
2554  let Inst{20-5}  = imm;
2555  let Inst{4-0}   = Rd;
2556
2557  let DecoderMethod = "DecodeMoveImmInstruction";
2558}
2559
2560multiclass MoveImmediate<bits<2> opc, string asm> {
2561  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2562    let Inst{31} = 0;
2563  }
2564
2565  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2566    let Inst{31} = 1;
2567  }
2568}
2569
2570let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2571class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2572                          string asm>
2573  : I<(outs regtype:$Rd),
2574      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2575       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2576    Sched<[WriteI, ReadI]> {
2577  bits<5> Rd;
2578  bits<16> imm;
2579  bits<6> shift;
2580  let Inst{30-29} = opc;
2581  let Inst{28-23} = 0b100101;
2582  let Inst{22-21} = shift{5-4};
2583  let Inst{20-5}  = imm;
2584  let Inst{4-0}   = Rd;
2585
2586  let DecoderMethod = "DecodeMoveImmInstruction";
2587}
2588
2589multiclass InsertImmediate<bits<2> opc, string asm> {
2590  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2591    let Inst{31} = 0;
2592  }
2593
2594  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2595    let Inst{31} = 1;
2596  }
2597}
2598
2599//---
2600// Add/Subtract
2601//---
2602
2603class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2604                    string asm_inst, string asm_ops,
2605                    dag inputs, dag pattern>
2606    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2607      Sched<[WriteI, ReadI]> {
2608  bits<5>  Rd;
2609  bits<5>  Rn;
2610  let Inst{30}    = isSub;
2611  let Inst{29}    = setFlags;
2612  let Inst{28-24} = 0b10001;
2613  let Inst{9-5}   = Rn;
2614  let Inst{4-0}   = Rd;
2615}
2616
2617class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2618                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2619                     string asm_inst, SDPatternOperator OpNode>
2620    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2621                    (ins srcRegtype:$Rn, immtype:$imm),
2622                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2623  bits<14> imm;
2624  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2625  let Inst{21-10} = imm{11-0};
2626  let DecoderMethod = "DecodeAddSubImmShift";
2627}
2628
2629class BaseAddSubRegPseudo<RegisterClass regtype,
2630                          SDPatternOperator OpNode>
2631    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2632             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2633      Sched<[WriteI, ReadI, ReadI]>;
2634
2635class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2636                     arith_shifted_reg shifted_regtype, string asm,
2637                     SDPatternOperator OpNode>
2638    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
2639        asm, "\t$Rd, $Rn, $Rm_and_shift", "",
2640        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm_and_shift))]>,
2641      Sched<[WriteISReg, ReadI, ReadISReg]> {
2642  bits<5> Rd;
2643  bits<5> Rn;
2644  bits<5> Rm;
2645  bits<8> shift;
2646  let Inst{30}    = isSub;
2647  let Inst{29}    = setFlags;
2648  let Inst{28-24} = 0b01011;
2649  let Inst{23-22} = shift{7-6};
2650  let Inst{21}    = 0;
2651  let Inst{20-16} = Rm;
2652  let Inst{15-10} = shift{5-0};
2653  let Inst{9-5}   = Rn;
2654  let Inst{4-0}   = Rd;
2655
2656  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2657}
2658
2659class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2660                     RegisterClass src1Regtype, Operand src2Regtype,
2661                     string asm, SDPatternOperator OpNode>
2662    : I<(outs dstRegtype:$Rd),
2663        (ins src1Regtype:$Rn, (src2Regtype $Rm, $extend):$Rm_and_extend),
2664        asm, "\t$Rd, $Rn, $Rm_and_extend", "",
2665        [(set dstRegtype:$Rd, (OpNode src1Regtype:$Rn, src2Regtype:$Rm_and_extend))]>,
2666      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2667  bits<5> Rd;
2668  bits<5> Rn;
2669  bits<5> Rm;
2670  bits<6> extend;
2671  let Inst{30}    = isSub;
2672  let Inst{29}    = setFlags;
2673  let Inst{28-24} = 0b01011;
2674  let Inst{23-21} = 0b001;
2675  let Inst{20-16} = Rm;
2676  let Inst{15-13} = extend{5-3};
2677  let Inst{12-10} = extend{2-0};
2678  let Inst{9-5}   = Rn;
2679  let Inst{4-0}   = Rd;
2680
2681  let DecoderMethod = "DecodeAddSubERegInstruction";
2682}
2683
2684let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2685class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2686                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2687                       Operand ext_op, string asm>
2688    : I<(outs dstRegtype:$Rd),
2689        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2690        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2691      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2692  bits<5> Rd;
2693  bits<5> Rn;
2694  bits<5> Rm;
2695  bits<6> ext;
2696  let Inst{30}    = isSub;
2697  let Inst{29}    = setFlags;
2698  let Inst{28-24} = 0b01011;
2699  let Inst{23-21} = 0b001;
2700  let Inst{20-16} = Rm;
2701  let Inst{15}    = ext{5};
2702  let Inst{12-10} = ext{2-0};
2703  let Inst{9-5}   = Rn;
2704  let Inst{4-0}   = Rd;
2705
2706  let DecoderMethod = "DecodeAddSubERegInstruction";
2707}
2708
2709// Aliases for register+register add/subtract.
2710class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2711                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2712                     int shiftExt>
2713    : InstAlias<asm#"\t$dst, $src1, $src2",
2714                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2715                      shiftExt)>;
2716
2717multiclass AddSub<bit isSub, string mnemonic, string alias,
2718                  SDPatternOperator OpNode = null_frag> {
2719  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2720  // Add/Subtract immediate
2721  // Increase the weight of the immediate variant to try to match it before
2722  // the extended register variant.
2723  // We used to match the register variant before the immediate when the
2724  // register argument could be implicitly zero-extended.
2725  let AddedComplexity = 6 in
2726  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2727                           mnemonic, OpNode> {
2728    let Inst{31} = 0;
2729  }
2730  let AddedComplexity = 6 in
2731  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2732                           mnemonic, OpNode> {
2733    let Inst{31} = 1;
2734  }
2735
2736  // Add/Subtract register - Only used for CodeGen
2737  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2738  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2739
2740  // Add/Subtract shifted register
2741  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2742                           OpNode> {
2743    let Inst{31} = 0;
2744  }
2745  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2746                           OpNode> {
2747    let Inst{31} = 1;
2748  }
2749  }
2750
2751  // Add/Subtract extended register
2752  let AddedComplexity = 1, hasSideEffects = 0 in {
2753  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2754                           arith_extended_reg32_i32, mnemonic, OpNode> {
2755    let Inst{31} = 0;
2756  }
2757  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2758                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2759    let Inst{31} = 1;
2760  }
2761  }
2762
2763  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2764                               arith_extendlsl64, mnemonic> {
2765    // UXTX and SXTX only.
2766    let Inst{14-13} = 0b11;
2767    let Inst{31} = 1;
2768  }
2769
2770  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2771  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2772                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2773                      addsub_shifted_imm32_neg:$imm), 0>;
2774  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2775                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2776                       addsub_shifted_imm64_neg:$imm), 0>;
2777
2778  // Register/register aliases with no shift when SP is not used.
2779  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2780                       GPR32, GPR32, GPR32, 0>;
2781  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2782                       GPR64, GPR64, GPR64, 0>;
2783
2784  // Register/register aliases with no shift when either the destination or
2785  // first source register is SP.
2786  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2787                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2788  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2789                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2790  def : AddSubRegAlias<mnemonic,
2791                       !cast<Instruction>(NAME#"Xrx64"),
2792                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2793  def : AddSubRegAlias<mnemonic,
2794                       !cast<Instruction>(NAME#"Xrx64"),
2795                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2796}
2797
2798multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2799                   string alias, string cmpAlias> {
2800  let isCompare = 1, Defs = [NZCV] in {
2801  // Add/Subtract immediate
2802  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2803                           mnemonic, OpNode> {
2804    let Inst{31} = 0;
2805  }
2806  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2807                           mnemonic, OpNode> {
2808    let Inst{31} = 1;
2809  }
2810
2811  // Add/Subtract register
2812  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2813  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2814
2815  // Add/Subtract shifted register
2816  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2817                           OpNode> {
2818    let Inst{31} = 0;
2819  }
2820  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2821                           OpNode> {
2822    let Inst{31} = 1;
2823  }
2824
2825  // Add/Subtract extended register
2826  let AddedComplexity = 1 in {
2827  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2828                           arith_extended_reg32_i32, mnemonic, OpNode> {
2829    let Inst{31} = 0;
2830  }
2831  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2832                           arith_extended_reg32_i64, mnemonic, OpNode> {
2833    let Inst{31} = 1;
2834  }
2835  }
2836
2837  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2838                               arith_extendlsl64, mnemonic> {
2839    // UXTX and SXTX only.
2840    let Inst{14-13} = 0b11;
2841    let Inst{31} = 1;
2842  }
2843  } // Defs = [NZCV]
2844
2845  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2846  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2847                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2848                      addsub_shifted_imm32_neg:$imm), 0>;
2849  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2850                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2851                       addsub_shifted_imm64_neg:$imm), 0>;
2852
2853  // Compare aliases
2854  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2855                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2856  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2857                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2858  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2859                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2860  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2861                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2862  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2863                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2864  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2865                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2866  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2867                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2868
2869  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2870  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2871                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2872  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2873                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2874
2875  // Compare shorthands
2876  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2877                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2878  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2879                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2880  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2881                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2882  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2883                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2884
2885  // Register/register aliases with no shift when SP is not used.
2886  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2887                       GPR32, GPR32, GPR32, 0>;
2888  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2889                       GPR64, GPR64, GPR64, 0>;
2890
2891  // Register/register aliases with no shift when the first source register
2892  // is SP.
2893  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2894                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2895  def : AddSubRegAlias<mnemonic,
2896                       !cast<Instruction>(NAME#"Xrx64"),
2897                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2898}
2899
2900class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2901      : BaseAddSubImm<
2902          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2903          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2904          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2905  bits<6> imm6;
2906  bits<4> imm4;
2907  let Inst{31} = 1;
2908  let Inst{23-22} = 0b10;
2909  let Inst{21-16} = imm6;
2910  let Inst{15-14} = 0b00;
2911  let Inst{13-10} = imm4;
2912  let Unpredictable{15-14} = 0b11;
2913}
2914
2915class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2916      : BaseTwoOperandRegReg<0b1, setsFlags, 0b000000, GPR64, asm_instr, OpNode,
2917                             GPR64sp, GPR64sp>;
2918
2919//---
2920// Extract
2921//---
2922def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2923                                      SDTCisPtrTy<3>]>;
2924def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2925
2926class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2927                     list<dag> patterns>
2928    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2929         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2930      Sched<[WriteExtr, ReadExtrHi]> {
2931  bits<5> Rd;
2932  bits<5> Rn;
2933  bits<5> Rm;
2934  bits<6> imm;
2935
2936  let Inst{30-23} = 0b00100111;
2937  let Inst{21}    = 0;
2938  let Inst{20-16} = Rm;
2939  let Inst{15-10} = imm;
2940  let Inst{9-5}   = Rn;
2941  let Inst{4-0}   = Rd;
2942}
2943
2944multiclass ExtractImm<string asm> {
2945  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2946                      [(set GPR32:$Rd,
2947                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2948    let Inst{31} = 0;
2949    let Inst{22} = 0;
2950    // imm<5> must be zero.
2951    let imm{5}   = 0;
2952  }
2953  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2954                      [(set GPR64:$Rd,
2955                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2956
2957    let Inst{31} = 1;
2958    let Inst{22} = 1;
2959  }
2960}
2961
2962//---
2963// Bitfield
2964//---
2965
2966let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2967class BaseBitfieldImm<bits<2> opc,
2968                      RegisterClass regtype, Operand imm_type, string asm>
2969    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2970         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2971      Sched<[WriteIS, ReadI]> {
2972  bits<5> Rd;
2973  bits<5> Rn;
2974  bits<6> immr;
2975  bits<6> imms;
2976
2977  let Inst{30-29} = opc;
2978  let Inst{28-23} = 0b100110;
2979  let Inst{21-16} = immr;
2980  let Inst{15-10} = imms;
2981  let Inst{9-5}   = Rn;
2982  let Inst{4-0}   = Rd;
2983}
2984
2985multiclass BitfieldImm<bits<2> opc, string asm> {
2986  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2987    let Inst{31} = 0;
2988    let Inst{22} = 0;
2989    // imms<5> and immr<5> must be zero, else ReservedValue().
2990    let Inst{21} = 0;
2991    let Inst{15} = 0;
2992  }
2993  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2994    let Inst{31} = 1;
2995    let Inst{22} = 1;
2996  }
2997}
2998
2999let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3000class BaseBitfieldImmWith2RegArgs<bits<2> opc,
3001                      RegisterClass regtype, Operand imm_type, string asm>
3002    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
3003                             imm_type:$imms),
3004         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
3005      Sched<[WriteIS, ReadI]> {
3006  bits<5> Rd;
3007  bits<5> Rn;
3008  bits<6> immr;
3009  bits<6> imms;
3010
3011  let Inst{30-29} = opc;
3012  let Inst{28-23} = 0b100110;
3013  let Inst{21-16} = immr;
3014  let Inst{15-10} = imms;
3015  let Inst{9-5}   = Rn;
3016  let Inst{4-0}   = Rd;
3017}
3018
3019multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
3020  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
3021    let Inst{31} = 0;
3022    let Inst{22} = 0;
3023    // imms<5> and immr<5> must be zero, else ReservedValue().
3024    let Inst{21} = 0;
3025    let Inst{15} = 0;
3026  }
3027  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
3028    let Inst{31} = 1;
3029    let Inst{22} = 1;
3030  }
3031}
3032
3033//---
3034// Logical
3035//---
3036
3037// Logical (immediate)
3038class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
3039                     RegisterClass sregtype, Operand imm_type, string asm,
3040                     list<dag> pattern>
3041    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
3042         asm, "\t$Rd, $Rn, $imm", "", pattern>,
3043      Sched<[WriteI, ReadI]> {
3044  bits<5>  Rd;
3045  bits<5>  Rn;
3046  bits<13> imm;
3047  let Inst{30-29} = opc;
3048  let Inst{28-23} = 0b100100;
3049  let Inst{22}    = imm{12};
3050  let Inst{21-16} = imm{11-6};
3051  let Inst{15-10} = imm{5-0};
3052  let Inst{9-5}   = Rn;
3053  let Inst{4-0}   = Rd;
3054
3055  let DecoderMethod = "DecodeLogicalImmInstruction";
3056}
3057
3058// Logical (shifted register)
3059class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
3060                      logical_shifted_reg shifted_regtype, string asm,
3061                      list<dag> pattern>
3062    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
3063        asm, "\t$Rd, $Rn, $Rm_and_shift", "", pattern>,
3064      Sched<[WriteISReg, ReadI, ReadISReg]> {
3065  bits<5> Rd;
3066  bits<5> Rn;
3067  bits<5> Rm;
3068  bits<8> shift;
3069  let Inst{30-29} = opc;
3070  let Inst{28-24} = 0b01010;
3071  let Inst{23-22} = shift{7-6};
3072  let Inst{21}    = N;
3073  let Inst{20-16} = Rm;
3074  let Inst{15-10} = shift{5-0};
3075  let Inst{9-5}   = Rn;
3076  let Inst{4-0}   = Rd;
3077
3078  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
3079}
3080
3081// Aliases for register+register logical instructions.
3082class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
3083    : InstAlias<asm#"\t$dst, $src1, $src2",
3084                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
3085
3086multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
3087                      string Alias> {
3088  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3089  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
3090                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
3091                                               logical_imm32:$imm))]> {
3092    let Inst{31} = 0;
3093    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3094  }
3095  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3096  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
3097                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
3098                                               logical_imm64:$imm))]> {
3099    let Inst{31} = 1;
3100  }
3101
3102  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3103                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
3104                      logical_imm32_not:$imm), 0>;
3105  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3106                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
3107                       logical_imm64_not:$imm), 0>;
3108}
3109
3110multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
3111                       string Alias> {
3112  let isCompare = 1, Defs = [NZCV] in {
3113  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
3114      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
3115    let Inst{31} = 0;
3116    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3117  }
3118  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
3119      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
3120    let Inst{31} = 1;
3121  }
3122  } // end Defs = [NZCV]
3123
3124  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3125                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
3126                      logical_imm32_not:$imm), 0>;
3127  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3128                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
3129                       logical_imm64_not:$imm), 0>;
3130}
3131
3132class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
3133    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3134             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
3135      Sched<[WriteI, ReadI, ReadI]>;
3136
3137// Split from LogicalImm as not all instructions have both.
3138multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
3139                      SDPatternOperator OpNode, int AddedComplexityVal = 0> {
3140  let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = AddedComplexityVal in {
3141  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3142  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3143  }
3144
3145  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3146                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3147                                                 logical_shifted_reg32:$Rm_and_shift))]> {
3148    let Inst{31} = 0;
3149  }
3150  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3151                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3152                                                 logical_shifted_reg64:$Rm_and_shift))]> {
3153    let Inst{31} = 1;
3154  }
3155
3156  def : LogicalRegAlias<mnemonic,
3157                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3158  def : LogicalRegAlias<mnemonic,
3159                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3160}
3161
3162// Split from LogicalReg to allow setting NZCV Defs
3163multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3164                       SDPatternOperator OpNode = null_frag> {
3165  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3166  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3167  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3168
3169  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3170            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm_and_shift))]> {
3171    let Inst{31} = 0;
3172  }
3173  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3174            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm_and_shift))]> {
3175    let Inst{31} = 1;
3176  }
3177  } // Defs = [NZCV]
3178
3179  def : LogicalRegAlias<mnemonic,
3180                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3181  def : LogicalRegAlias<mnemonic,
3182                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3183}
3184
3185//---
3186// Conditionally set flags
3187//---
3188
3189let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3190class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3191                            string mnemonic, SDNode OpNode>
3192    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3193         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3194         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3195                             (i32 imm:$cond), NZCV))]>,
3196      Sched<[WriteI, ReadI]> {
3197  let Uses = [NZCV];
3198  let Defs = [NZCV];
3199
3200  bits<5> Rn;
3201  bits<5> imm;
3202  bits<4> nzcv;
3203  bits<4> cond;
3204
3205  let Inst{30}    = op;
3206  let Inst{29-21} = 0b111010010;
3207  let Inst{20-16} = imm;
3208  let Inst{15-12} = cond;
3209  let Inst{11-10} = 0b10;
3210  let Inst{9-5}   = Rn;
3211  let Inst{4}     = 0b0;
3212  let Inst{3-0}   = nzcv;
3213}
3214
3215let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3216class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3217                            SDNode OpNode>
3218    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3219         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3220         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3221                             (i32 imm:$cond), NZCV))]>,
3222      Sched<[WriteI, ReadI, ReadI]> {
3223  let Uses = [NZCV];
3224  let Defs = [NZCV];
3225
3226  bits<5> Rn;
3227  bits<5> Rm;
3228  bits<4> nzcv;
3229  bits<4> cond;
3230
3231  let Inst{30}    = op;
3232  let Inst{29-21} = 0b111010010;
3233  let Inst{20-16} = Rm;
3234  let Inst{15-12} = cond;
3235  let Inst{11-10} = 0b00;
3236  let Inst{9-5}   = Rn;
3237  let Inst{4}     = 0b0;
3238  let Inst{3-0}   = nzcv;
3239}
3240
3241multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3242  // immediate operand variants
3243  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3244    let Inst{31} = 0;
3245  }
3246  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3247    let Inst{31} = 1;
3248  }
3249  // register operand variants
3250  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3251    let Inst{31} = 0;
3252  }
3253  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3254    let Inst{31} = 1;
3255  }
3256}
3257
3258//---
3259// Conditional select
3260//---
3261
3262class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3263    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3264         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3265         [(set regtype:$Rd,
3266               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3267      Sched<[WriteI, ReadI, ReadI]> {
3268  let Uses = [NZCV];
3269
3270  bits<5> Rd;
3271  bits<5> Rn;
3272  bits<5> Rm;
3273  bits<4> cond;
3274
3275  let Inst{30}    = op;
3276  let Inst{29-21} = 0b011010100;
3277  let Inst{20-16} = Rm;
3278  let Inst{15-12} = cond;
3279  let Inst{11-10} = op2;
3280  let Inst{9-5}   = Rn;
3281  let Inst{4-0}   = Rd;
3282}
3283
3284multiclass CondSelect<bit op, bits<2> op2, string asm> {
3285  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3286    let Inst{31} = 0;
3287  }
3288  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3289    let Inst{31} = 1;
3290  }
3291}
3292
3293class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3294                       PatFrag frag>
3295    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3296         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3297         [(set regtype:$Rd,
3298               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3299               (i32 imm:$cond), NZCV))]>,
3300      Sched<[WriteI, ReadI, ReadI]> {
3301  let Uses = [NZCV];
3302
3303  bits<5> Rd;
3304  bits<5> Rn;
3305  bits<5> Rm;
3306  bits<4> cond;
3307
3308  let Inst{30}    = op;
3309  let Inst{29-21} = 0b011010100;
3310  let Inst{20-16} = Rm;
3311  let Inst{15-12} = cond;
3312  let Inst{11-10} = op2;
3313  let Inst{9-5}   = Rn;
3314  let Inst{4-0}   = Rd;
3315}
3316
3317def inv_cond_XFORM : SDNodeXForm<imm, [{
3318  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3319  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3320                                   MVT::i32);
3321}]>;
3322
3323multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3324  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3325    let Inst{31} = 0;
3326  }
3327  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3328    let Inst{31} = 1;
3329  }
3330
3331  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3332            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3333                                           (inv_cond_XFORM imm:$cond))>;
3334
3335  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3336            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3337                                           (inv_cond_XFORM imm:$cond))>;
3338}
3339
3340//---
3341// Special Mask Value
3342//---
3343def maski8_or_more : Operand<i32>,
3344  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3345}
3346def maski16_or_more : Operand<i32>,
3347  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3348}
3349
3350
3351//---
3352// Load/store
3353//---
3354
3355// (unsigned immediate)
3356// Indexed for 8-bit registers. offset is in range [0,4095].
3357def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3358def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3359def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3360def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3361def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3362
3363// (unsigned immediate)
3364// Indexed for 8-bit registers. offset is in range [0,63].
3365def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3366def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3367def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3368def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3369
3370def gi_am_indexed8 :
3371    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3372    GIComplexPatternEquiv<am_indexed8>;
3373def gi_am_indexed16 :
3374    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3375    GIComplexPatternEquiv<am_indexed16>;
3376def gi_am_indexed32 :
3377    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3378    GIComplexPatternEquiv<am_indexed32>;
3379def gi_am_indexed64 :
3380    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3381    GIComplexPatternEquiv<am_indexed64>;
3382def gi_am_indexed128 :
3383    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3384    GIComplexPatternEquiv<am_indexed128>;
3385
3386class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3387  let Name = "UImm12Offset" # Scale;
3388  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3389  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3390  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3391}
3392
3393def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3394def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3395def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3396def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3397def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3398
3399class uimm12_scaled<int Scale> : Operand<i64> {
3400  let ParserMatchClass
3401   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3402  let EncoderMethod
3403   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3404  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3405}
3406
3407def uimm12s1 : uimm12_scaled<1>;
3408def uimm12s2 : uimm12_scaled<2>;
3409def uimm12s4 : uimm12_scaled<4>;
3410def uimm12s8 : uimm12_scaled<8>;
3411def uimm12s16 : uimm12_scaled<16>;
3412
3413class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3414                      string asm, list<dag> pattern>
3415    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3416  bits<5> Rt;
3417
3418  bits<5> Rn;
3419  bits<12> offset;
3420
3421  let Inst{31-30} = sz;
3422  let Inst{29-27} = 0b111;
3423  let Inst{26}    = V;
3424  let Inst{25-24} = 0b01;
3425  let Inst{23-22} = opc;
3426  let Inst{21-10} = offset;
3427  let Inst{9-5}   = Rn;
3428  let Inst{4-0}   = Rt;
3429
3430  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3431}
3432
3433multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3434                  Operand indextype, string asm, list<dag> pattern> {
3435  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3436  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3437                           (ins GPR64sp:$Rn, indextype:$offset),
3438                           asm, pattern>,
3439           Sched<[WriteLD]>;
3440
3441  def : InstAlias<asm # "\t$Rt, [$Rn]",
3442                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3443}
3444
3445multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3446             Operand indextype, string asm, list<dag> pattern> {
3447  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3448  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3449                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3450                           asm, pattern>,
3451           Sched<[WriteST]>;
3452
3453  def : InstAlias<asm # "\t$Rt, [$Rn]",
3454                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3455}
3456
3457// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3458// substitute zero-registers automatically.
3459//
3460// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3461//       into StoreUI.
3462multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3463             Operand indextype, string asm, list<dag> pattern> {
3464  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3465  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3466                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3467                           asm, pattern>,
3468           Sched<[WriteST]>;
3469
3470  def : InstAlias<asm # "\t$Rt, [$Rn]",
3471                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3472}
3473
3474def PrefetchOperand : AsmOperandClass {
3475  let Name = "Prefetch";
3476  let ParserMethod = "tryParsePrefetch";
3477}
3478def prfop : Operand<i32> {
3479  let PrintMethod = "printPrefetchOp";
3480  let ParserMatchClass = PrefetchOperand;
3481}
3482
3483let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3484class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3485    : BaseLoadStoreUI<sz, V, opc,
3486                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3487                      asm, pat>,
3488      Sched<[WriteLD]>;
3489
3490//---
3491// Load literal
3492//---
3493
3494// Load literal address: 19-bit immediate. The low two bits of the target
3495// offset are implied zero and so are not part of the immediate.
3496def am_ldrlit : Operand<iPTR> {
3497  let EncoderMethod = "getLoadLiteralOpValue";
3498  let DecoderMethod = "DecodePCRelLabel19";
3499  let PrintMethod = "printAlignedLabel";
3500  let ParserMatchClass = PCRelLabel19Operand;
3501  let OperandType = "OPERAND_PCREL";
3502}
3503
3504let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3505class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3506    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3507        asm, "\t$Rt, $label", "", pat>,
3508      Sched<[WriteLD]> {
3509  bits<5> Rt;
3510  bits<19> label;
3511  let Inst{31-30} = opc;
3512  let Inst{29-27} = 0b011;
3513  let Inst{26}    = V;
3514  let Inst{25-24} = 0b00;
3515  let Inst{23-5}  = label;
3516  let Inst{4-0}   = Rt;
3517}
3518
3519let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3520class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3521    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3522        asm, "\t$Rt, $label", "", pat>,
3523      Sched<[WriteLD]> {
3524  bits<5> Rt;
3525  bits<19> label;
3526  let Inst{31-30} = opc;
3527  let Inst{29-27} = 0b011;
3528  let Inst{26}    = V;
3529  let Inst{25-24} = 0b00;
3530  let Inst{23-5}  = label;
3531  let Inst{4-0}   = Rt;
3532}
3533
3534//---
3535// Load/store register offset
3536//---
3537
3538def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3539def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3540def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3541def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3542def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3543
3544def gi_ro_Xindexed8 :
3545    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3546    GIComplexPatternEquiv<ro_Xindexed8>;
3547def gi_ro_Xindexed16 :
3548    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3549    GIComplexPatternEquiv<ro_Xindexed16>;
3550def gi_ro_Xindexed32 :
3551    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3552    GIComplexPatternEquiv<ro_Xindexed32>;
3553def gi_ro_Xindexed64 :
3554    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3555    GIComplexPatternEquiv<ro_Xindexed64>;
3556def gi_ro_Xindexed128 :
3557    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3558    GIComplexPatternEquiv<ro_Xindexed128>;
3559
3560def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3561def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3562def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3563def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3564def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3565
3566def gi_ro_Windexed8 :
3567    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3568    GIComplexPatternEquiv<ro_Windexed8>;
3569def gi_ro_Windexed16 :
3570    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3571    GIComplexPatternEquiv<ro_Windexed16>;
3572def gi_ro_Windexed32 :
3573    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3574    GIComplexPatternEquiv<ro_Windexed32>;
3575def gi_ro_Windexed64 :
3576    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3577    GIComplexPatternEquiv<ro_Windexed64>;
3578def gi_ro_Windexed128 :
3579    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3580    GIComplexPatternEquiv<ro_Windexed128>;
3581
3582class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3583  let Name = "Mem" # Reg # "Extend" # Width;
3584  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3585  let RenderMethod = "addMemExtendOperands";
3586  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3587}
3588
3589def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3590  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3591  // the trivial shift.
3592  let RenderMethod = "addMemExtend8Operands";
3593}
3594def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3595def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3596def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3597def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3598
3599def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3600  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3601  // the trivial shift.
3602  let RenderMethod = "addMemExtend8Operands";
3603}
3604def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3605def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3606def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3607def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3608
3609class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3610        : Operand<i32> {
3611  let ParserMatchClass = ParserClass;
3612  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3613  let DecoderMethod = "DecodeMemExtend";
3614  let EncoderMethod = "getMemExtendOpValue";
3615  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3616}
3617
3618def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3619def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3620def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3621def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3622def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3623
3624def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3625def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3626def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3627def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3628def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3629
3630class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3631                  Operand wextend, Operand xextend>  {
3632  // CodeGen-level pattern covering the entire addressing mode.
3633  ComplexPattern Wpat = windex;
3634  ComplexPattern Xpat = xindex;
3635
3636  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3637  Operand Wext = wextend;
3638  Operand Xext = xextend;
3639}
3640
3641def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3642def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3643def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3644def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3645def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3646                       ro_Xextend128>;
3647
3648class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3649                   dag outs, list<dag> pat>
3650    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3651  bits<5> Rt;
3652  bits<5> Rn;
3653  bits<5> Rm;
3654  bits<2> extend;
3655  let Inst{31-30} = sz;
3656  let Inst{29-27} = 0b111;
3657  let Inst{26}    = V;
3658  let Inst{25-24} = 0b00;
3659  let Inst{23-22} = opc;
3660  let Inst{21}    = 1;
3661  let Inst{20-16} = Rm;
3662  let Inst{15}    = extend{1}; // sign extend Rm?
3663  let Inst{14}    = 1;
3664  let Inst{12}    = extend{0}; // do shift?
3665  let Inst{11-10} = 0b10;
3666  let Inst{9-5}   = Rn;
3667  let Inst{4-0}   = Rt;
3668}
3669
3670class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3671  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3672              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3673
3674multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3675                   string asm, ValueType Ty, SDPatternOperator loadop> {
3676  let AddedComplexity = 10 in
3677  def roW : LoadStore8RO<sz, V, opc, asm,
3678                 (outs regtype:$Rt),
3679                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3680                 [(set (Ty regtype:$Rt),
3681                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3682                                             ro_Wextend8:$extend)))]>,
3683           Sched<[WriteLDIdx, ReadAdrBase]> {
3684    let Inst{13} = 0b0;
3685  }
3686
3687  let AddedComplexity = 10 in
3688  def roX : LoadStore8RO<sz, V, opc, asm,
3689                 (outs regtype:$Rt),
3690                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3691                 [(set (Ty regtype:$Rt),
3692                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3693                                             ro_Xextend8:$extend)))]>,
3694           Sched<[WriteLDIdx, ReadAdrBase]> {
3695    let Inst{13} = 0b1;
3696  }
3697
3698  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3699}
3700
3701multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3702                    string asm, ValueType Ty, SDPatternOperator storeop> {
3703  let AddedComplexity = 10 in
3704  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3705                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3706                 [(storeop (Ty regtype:$Rt),
3707                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3708                                         ro_Wextend8:$extend))]>,
3709            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3710    let Inst{13} = 0b0;
3711  }
3712
3713  let AddedComplexity = 10 in
3714  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3715                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3716                 [(storeop (Ty regtype:$Rt),
3717                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3718                                         ro_Xextend8:$extend))]>,
3719            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3720    let Inst{13} = 0b1;
3721  }
3722
3723  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3724}
3725
3726class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3727                    dag outs, list<dag> pat>
3728    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3729  bits<5> Rt;
3730  bits<5> Rn;
3731  bits<5> Rm;
3732  bits<2> extend;
3733  let Inst{31-30} = sz;
3734  let Inst{29-27} = 0b111;
3735  let Inst{26}    = V;
3736  let Inst{25-24} = 0b00;
3737  let Inst{23-22} = opc;
3738  let Inst{21}    = 1;
3739  let Inst{20-16} = Rm;
3740  let Inst{15}    = extend{1}; // sign extend Rm?
3741  let Inst{14}    = 1;
3742  let Inst{12}    = extend{0}; // do shift?
3743  let Inst{11-10} = 0b10;
3744  let Inst{9-5}   = Rn;
3745  let Inst{4-0}   = Rt;
3746}
3747
3748multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3749                    string asm, ValueType Ty, SDPatternOperator loadop> {
3750  let AddedComplexity = 10 in
3751  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3752                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3753                 [(set (Ty regtype:$Rt),
3754                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3755                                              ro_Wextend16:$extend)))]>,
3756            Sched<[WriteLDIdx, ReadAdrBase]> {
3757    let Inst{13} = 0b0;
3758  }
3759
3760  let AddedComplexity = 10 in
3761  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3762                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3763                 [(set (Ty regtype:$Rt),
3764                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3765                                             ro_Xextend16:$extend)))]>,
3766            Sched<[WriteLDIdx, ReadAdrBase]> {
3767    let Inst{13} = 0b1;
3768  }
3769
3770  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3771}
3772
3773multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3774                     string asm, ValueType Ty, SDPatternOperator storeop> {
3775  let AddedComplexity = 10 in
3776  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3777                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3778                [(storeop (Ty regtype:$Rt),
3779                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3780                                         ro_Wextend16:$extend))]>,
3781           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3782    let Inst{13} = 0b0;
3783  }
3784
3785  let AddedComplexity = 10 in
3786  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3787                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3788                [(storeop (Ty regtype:$Rt),
3789                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3790                                         ro_Xextend16:$extend))]>,
3791           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3792    let Inst{13} = 0b1;
3793  }
3794
3795  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3796}
3797
3798class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3799                    dag outs, list<dag> pat>
3800    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3801  bits<5> Rt;
3802  bits<5> Rn;
3803  bits<5> Rm;
3804  bits<2> extend;
3805  let Inst{31-30} = sz;
3806  let Inst{29-27} = 0b111;
3807  let Inst{26}    = V;
3808  let Inst{25-24} = 0b00;
3809  let Inst{23-22} = opc;
3810  let Inst{21}    = 1;
3811  let Inst{20-16} = Rm;
3812  let Inst{15}    = extend{1}; // sign extend Rm?
3813  let Inst{14}    = 1;
3814  let Inst{12}    = extend{0}; // do shift?
3815  let Inst{11-10} = 0b10;
3816  let Inst{9-5}   = Rn;
3817  let Inst{4-0}   = Rt;
3818}
3819
3820multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3821                    string asm, ValueType Ty, SDPatternOperator loadop> {
3822  let AddedComplexity = 10 in
3823  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3824                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3825                 [(set (Ty regtype:$Rt),
3826                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3827                                              ro_Wextend32:$extend)))]>,
3828           Sched<[WriteLDIdx, ReadAdrBase]> {
3829    let Inst{13} = 0b0;
3830  }
3831
3832  let AddedComplexity = 10 in
3833  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3834                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3835                 [(set (Ty regtype:$Rt),
3836                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3837                                              ro_Xextend32:$extend)))]>,
3838           Sched<[WriteLDIdx, ReadAdrBase]> {
3839    let Inst{13} = 0b1;
3840  }
3841
3842  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3843}
3844
3845multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3846                     string asm, ValueType Ty, SDPatternOperator storeop> {
3847  let AddedComplexity = 10 in
3848  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3849                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3850                [(storeop (Ty regtype:$Rt),
3851                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3852                                         ro_Wextend32:$extend))]>,
3853            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3854    let Inst{13} = 0b0;
3855  }
3856
3857  let AddedComplexity = 10 in
3858  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3859                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3860                [(storeop (Ty regtype:$Rt),
3861                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3862                                        ro_Xextend32:$extend))]>,
3863            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3864    let Inst{13} = 0b1;
3865  }
3866
3867  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3868}
3869
3870class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3871                    dag outs, list<dag> pat>
3872    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3873  bits<5> Rt;
3874  bits<5> Rn;
3875  bits<5> Rm;
3876  bits<2> extend;
3877  let Inst{31-30} = sz;
3878  let Inst{29-27} = 0b111;
3879  let Inst{26}    = V;
3880  let Inst{25-24} = 0b00;
3881  let Inst{23-22} = opc;
3882  let Inst{21}    = 1;
3883  let Inst{20-16} = Rm;
3884  let Inst{15}    = extend{1}; // sign extend Rm?
3885  let Inst{14}    = 1;
3886  let Inst{12}    = extend{0}; // do shift?
3887  let Inst{11-10} = 0b10;
3888  let Inst{9-5}   = Rn;
3889  let Inst{4-0}   = Rt;
3890}
3891
3892multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3893                    string asm, ValueType Ty, SDPatternOperator loadop> {
3894  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3895  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3896                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3897                [(set (Ty regtype:$Rt),
3898                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3899                                             ro_Wextend64:$extend)))]>,
3900           Sched<[WriteLDIdx, ReadAdrBase]> {
3901    let Inst{13} = 0b0;
3902  }
3903
3904  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3905  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3906                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3907                 [(set (Ty regtype:$Rt),
3908                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3909                                              ro_Xextend64:$extend)))]>,
3910           Sched<[WriteLDIdx, ReadAdrBase]> {
3911    let Inst{13} = 0b1;
3912  }
3913
3914  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3915}
3916
3917multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3918                     string asm, ValueType Ty, SDPatternOperator storeop> {
3919  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3920  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
3921                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3922                [(storeop (Ty regtype:$Rt),
3923                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3924                                         ro_Wextend64:$extend))]>,
3925            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3926    let Inst{13} = 0b0;
3927  }
3928
3929  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3930  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
3931                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3932                [(storeop (Ty regtype:$Rt),
3933                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3934                                         ro_Xextend64:$extend))]>,
3935            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3936    let Inst{13} = 0b1;
3937  }
3938
3939  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3940}
3941
3942class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3943                     dag outs, list<dag> pat>
3944    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3945  bits<5> Rt;
3946  bits<5> Rn;
3947  bits<5> Rm;
3948  bits<2> extend;
3949  let Inst{31-30} = sz;
3950  let Inst{29-27} = 0b111;
3951  let Inst{26}    = V;
3952  let Inst{25-24} = 0b00;
3953  let Inst{23-22} = opc;
3954  let Inst{21}    = 1;
3955  let Inst{20-16} = Rm;
3956  let Inst{15}    = extend{1}; // sign extend Rm?
3957  let Inst{14}    = 1;
3958  let Inst{12}    = extend{0}; // do shift?
3959  let Inst{11-10} = 0b10;
3960  let Inst{9-5}   = Rn;
3961  let Inst{4-0}   = Rt;
3962}
3963
3964multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3965                     string asm, ValueType Ty, SDPatternOperator loadop> {
3966  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3967  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3968                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3969                 [(set (Ty regtype:$Rt),
3970                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3971                                               ro_Wextend128:$extend)))]>,
3972            Sched<[WriteLDIdx, ReadAdrBase]> {
3973    let Inst{13} = 0b0;
3974  }
3975
3976  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3977  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3978                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3979                 [(set (Ty regtype:$Rt),
3980                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3981                                               ro_Xextend128:$extend)))]>,
3982            Sched<[WriteLDIdx, ReadAdrBase]> {
3983    let Inst{13} = 0b1;
3984  }
3985
3986  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3987}
3988
3989multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3990                      string asm> {
3991  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3992  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
3993               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3994                []>,
3995            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3996    let Inst{13} = 0b0;
3997  }
3998
3999  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4000  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
4001               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4002                []>,
4003            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4004    let Inst{13} = 0b1;
4005  }
4006
4007  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4008}
4009
4010let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4011class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
4012                     string asm, list<dag> pat>
4013    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
4014      Sched<[WriteLD]> {
4015  bits<5> Rt;
4016  bits<5> Rn;
4017  bits<5> Rm;
4018  bits<2> extend;
4019  let Inst{31-30} = sz;
4020  let Inst{29-27} = 0b111;
4021  let Inst{26}    = V;
4022  let Inst{25-24} = 0b00;
4023  let Inst{23-22} = opc;
4024  let Inst{21}    = 1;
4025  let Inst{20-16} = Rm;
4026  let Inst{15}    = extend{1}; // sign extend Rm?
4027  let Inst{14}    = 1;
4028  let Inst{12}    = extend{0}; // do shift?
4029  let Inst{11-10} = 0b10;
4030  let Inst{9-5}   = Rn;
4031  let Inst{4-0}   = Rt;
4032  let DecoderMethod = "DecodePRFMRegInstruction";
4033  // PRFM (reg) aliases with RPRFM added to the base A64 instruction set. When
4034  // the decoder method returns Fail, the decoder should attempt to decode the
4035  // instruction as RPRFM.
4036  let hasCompleteDecoder = 0;
4037}
4038
4039multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
4040  def roW : BasePrefetchRO<sz, V, opc, (outs),
4041                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4042                asm, [(AArch64Prefetch timm:$Rt,
4043                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4044                                                    ro_Wextend64:$extend))]> {
4045    let Inst{13} = 0b0;
4046  }
4047
4048  def roX : BasePrefetchRO<sz, V, opc, (outs),
4049                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4050                asm,  [(AArch64Prefetch timm:$Rt,
4051                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4052                                                     ro_Xextend64:$extend))]> {
4053    let Inst{13} = 0b1;
4054  }
4055
4056  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
4057               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
4058                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
4059}
4060
4061//---
4062// Load/store unscaled immediate
4063//---
4064
4065def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
4066def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
4067def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
4068def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
4069def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
4070
4071def gi_am_unscaled8 :
4072    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
4073    GIComplexPatternEquiv<am_unscaled8>;
4074def gi_am_unscaled16 :
4075    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
4076    GIComplexPatternEquiv<am_unscaled16>;
4077def gi_am_unscaled32 :
4078    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
4079    GIComplexPatternEquiv<am_unscaled32>;
4080def gi_am_unscaled64 :
4081    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
4082    GIComplexPatternEquiv<am_unscaled64>;
4083def gi_am_unscaled128 :
4084    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
4085    GIComplexPatternEquiv<am_unscaled128>;
4086
4087
4088class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4089                           string asm, list<dag> pattern>
4090    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
4091  bits<5> Rt;
4092  bits<5> Rn;
4093  bits<9> offset;
4094  let Inst{31-30} = sz;
4095  let Inst{29-27} = 0b111;
4096  let Inst{26}    = V;
4097  let Inst{25-24} = 0b00;
4098  let Inst{23-22} = opc;
4099  let Inst{21}    = 0;
4100  let Inst{20-12} = offset;
4101  let Inst{11-10} = 0b00;
4102  let Inst{9-5}   = Rn;
4103  let Inst{4-0}   = Rt;
4104
4105  let DecoderMethod = "DecodeSignedLdStInstruction";
4106}
4107
4108// Armv8.4 LDAPR & STLR with Immediate Offset instruction
4109multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4110                              DAGOperand regtype > {
4111  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
4112                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
4113          Sched<[WriteST]> {
4114    let Inst{29} = 0;
4115    let Inst{24} = 1;
4116  }
4117  def : InstAlias<asm # "\t$Rt, [$Rn]",
4118                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4119}
4120
4121multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4122                               DAGOperand regtype > {
4123  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
4124                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4125                               asm, []>,
4126          Sched<[WriteST]> {
4127    let Inst{29} = 0;
4128    let Inst{24} = 1;
4129  }
4130  def : InstAlias<asm # "\t$Rt, [$Rn]",
4131                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4132}
4133
4134multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4135                   string asm, list<dag> pattern> {
4136  let AddedComplexity = 1 in // try this before LoadUI
4137  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
4138                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
4139          Sched<[WriteLD]>;
4140
4141  def : InstAlias<asm # "\t$Rt, [$Rn]",
4142                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4143}
4144
4145multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4146                         string asm, list<dag> pattern> {
4147  let AddedComplexity = 1 in // try this before StoreUI
4148  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4149                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4150                               asm, pattern>,
4151          Sched<[WriteST]>;
4152
4153  def : InstAlias<asm # "\t$Rt, [$Rn]",
4154                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4155}
4156
4157multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4158                            list<dag> pat> {
4159  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4160  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4161                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4162                               asm, pat>,
4163          Sched<[WriteLD]>;
4164
4165  def : InstAlias<asm # "\t$Rt, [$Rn]",
4166                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4167}
4168
4169//---
4170// Load/store unscaled immediate, unprivileged
4171//---
4172
4173class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4174                                dag oops, dag iops, string asm>
4175    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4176  bits<5> Rt;
4177  bits<5> Rn;
4178  bits<9> offset;
4179  let Inst{31-30} = sz;
4180  let Inst{29-27} = 0b111;
4181  let Inst{26}    = V;
4182  let Inst{25-24} = 0b00;
4183  let Inst{23-22} = opc;
4184  let Inst{21}    = 0;
4185  let Inst{20-12} = offset;
4186  let Inst{11-10} = 0b10;
4187  let Inst{9-5}   = Rn;
4188  let Inst{4-0}   = Rt;
4189
4190  let DecoderMethod = "DecodeSignedLdStInstruction";
4191}
4192
4193multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4194                            RegisterClass regtype, string asm> {
4195  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4196  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4197                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4198          Sched<[WriteLD]>;
4199
4200  def : InstAlias<asm # "\t$Rt, [$Rn]",
4201                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4202}
4203
4204multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4205                             RegisterClass regtype, string asm> {
4206  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4207  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4208                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4209                                 asm>,
4210          Sched<[WriteST]>;
4211
4212  def : InstAlias<asm # "\t$Rt, [$Rn]",
4213                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4214}
4215
4216//---
4217// Load/store pre-indexed
4218//---
4219
4220class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4221                          string asm, string cstr, list<dag> pat>
4222    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4223  bits<5> Rt;
4224  bits<5> Rn;
4225  bits<9> offset;
4226  let Inst{31-30} = sz;
4227  let Inst{29-27} = 0b111;
4228  let Inst{26}    = V;
4229  let Inst{25-24} = 0;
4230  let Inst{23-22} = opc;
4231  let Inst{21}    = 0;
4232  let Inst{20-12} = offset;
4233  let Inst{11-10} = 0b11;
4234  let Inst{9-5}   = Rn;
4235  let Inst{4-0}   = Rt;
4236
4237  let DecoderMethod = "DecodeSignedLdStInstruction";
4238}
4239
4240let hasSideEffects = 0 in {
4241let mayStore = 0, mayLoad = 1 in
4242class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4243             string asm>
4244    : BaseLoadStorePreIdx<sz, V, opc,
4245                     (outs GPR64sp:$wback, regtype:$Rt),
4246                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4247                     "$Rn = $wback,@earlyclobber $wback", []>,
4248      Sched<[WriteAdr, WriteLD]>;
4249
4250let mayStore = 1, mayLoad = 0 in
4251class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4252                  string asm, SDPatternOperator storeop, ValueType Ty>
4253    : BaseLoadStorePreIdx<sz, V, opc,
4254                      (outs GPR64sp:$wback),
4255                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4256                      asm, "$Rn = $wback,@earlyclobber $wback",
4257      [(set GPR64sp:$wback,
4258            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4259      Sched<[WriteAdr, WriteST]>;
4260} // hasSideEffects = 0
4261
4262//---
4263// Load/store post-indexed
4264//---
4265
4266class BaseLoadStorePostIdx<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} = 0b00;
4276  let Inst{23-22} = opc;
4277  let Inst{21}    = 0b0;
4278  let Inst{20-12} = offset;
4279  let Inst{11-10} = 0b01;
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 LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4289             string asm>
4290    : BaseLoadStorePostIdx<sz, V, opc,
4291                      (outs GPR64sp:$wback, regtype:$Rt),
4292                      (ins GPR64sp:$Rn, simm9:$offset),
4293                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4294      Sched<[WriteAdr, WriteLD]>;
4295
4296let mayStore = 1, mayLoad = 0 in
4297class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4298                   string asm, SDPatternOperator storeop, ValueType Ty>
4299    : BaseLoadStorePostIdx<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//---
4310// Load/store pair
4311//---
4312
4313// (indexed, offset)
4314
4315class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4316                              string asm>
4317    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4318  bits<5> Rt;
4319  bits<5> Rt2;
4320  bits<5> Rn;
4321  bits<7> offset;
4322  let Inst{31-30} = opc;
4323  let Inst{29-27} = 0b101;
4324  let Inst{26}    = V;
4325  let Inst{25-23} = 0b010;
4326  let Inst{22}    = L;
4327  let Inst{21-15} = offset;
4328  let Inst{14-10} = Rt2;
4329  let Inst{9-5}   = Rn;
4330  let Inst{4-0}   = Rt;
4331
4332  let DecoderMethod = "DecodePairLdStInstruction";
4333}
4334
4335multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4336                          Operand indextype, string asm> {
4337  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4338  def i : BaseLoadStorePairOffset<opc, V, 1,
4339                                  (outs regtype:$Rt, regtype:$Rt2),
4340                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4341          Sched<[WriteLD, WriteLDHi]>;
4342
4343  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4344                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4345                                                  GPR64sp:$Rn, 0)>;
4346}
4347
4348
4349multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4350                           Operand indextype, string asm> {
4351  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4352  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4353                                  (ins regtype:$Rt, regtype:$Rt2,
4354                                       GPR64sp:$Rn, indextype:$offset),
4355                                  asm>,
4356          Sched<[WriteSTP]>;
4357
4358  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4359                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4360                                                  GPR64sp:$Rn, 0)>;
4361}
4362
4363// (pre-indexed)
4364class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4365                              string asm>
4366    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4367  bits<5> Rt;
4368  bits<5> Rt2;
4369  bits<5> Rn;
4370  bits<7> offset;
4371  let Inst{31-30} = opc;
4372  let Inst{29-27} = 0b101;
4373  let Inst{26}    = V;
4374  let Inst{25-23} = 0b011;
4375  let Inst{22}    = L;
4376  let Inst{21-15} = offset;
4377  let Inst{14-10} = Rt2;
4378  let Inst{9-5}   = Rn;
4379  let Inst{4-0}   = Rt;
4380
4381  let DecoderMethod = "DecodePairLdStInstruction";
4382}
4383
4384let hasSideEffects = 0 in {
4385let mayStore = 0, mayLoad = 1 in
4386class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4387                     Operand indextype, string asm>
4388    : BaseLoadStorePairPreIdx<opc, V, 1,
4389                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4390                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4391      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4392
4393let mayStore = 1, mayLoad = 0 in
4394class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4395                      Operand indextype, string asm>
4396    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4397                             (ins regtype:$Rt, regtype:$Rt2,
4398                                  GPR64sp:$Rn, indextype:$offset),
4399                             asm>,
4400      Sched<[WriteAdr, WriteSTP]>;
4401} // hasSideEffects = 0
4402
4403// (post-indexed)
4404
4405class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4406                              string asm>
4407    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4408  bits<5> Rt;
4409  bits<5> Rt2;
4410  bits<5> Rn;
4411  bits<7> offset;
4412  let Inst{31-30} = opc;
4413  let Inst{29-27} = 0b101;
4414  let Inst{26}    = V;
4415  let Inst{25-23} = 0b001;
4416  let Inst{22}    = L;
4417  let Inst{21-15} = offset;
4418  let Inst{14-10} = Rt2;
4419  let Inst{9-5}   = Rn;
4420  let Inst{4-0}   = Rt;
4421
4422  let DecoderMethod = "DecodePairLdStInstruction";
4423}
4424
4425let hasSideEffects = 0 in {
4426let mayStore = 0, mayLoad = 1 in
4427class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4428                      Operand idxtype, string asm>
4429    : BaseLoadStorePairPostIdx<opc, V, 1,
4430                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4431                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4432      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4433
4434let mayStore = 1, mayLoad = 0 in
4435class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4436                       Operand idxtype, string asm>
4437    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4438                             (ins regtype:$Rt, regtype:$Rt2,
4439                                  GPR64sp:$Rn, idxtype:$offset),
4440                             asm>,
4441      Sched<[WriteAdr, WriteSTP]>;
4442} // hasSideEffects = 0
4443
4444//  (no-allocate)
4445
4446class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4447                              string asm>
4448    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4449  bits<5> Rt;
4450  bits<5> Rt2;
4451  bits<5> Rn;
4452  bits<7> offset;
4453  let Inst{31-30} = opc;
4454  let Inst{29-27} = 0b101;
4455  let Inst{26}    = V;
4456  let Inst{25-23} = 0b000;
4457  let Inst{22}    = L;
4458  let Inst{21-15} = offset;
4459  let Inst{14-10} = Rt2;
4460  let Inst{9-5}   = Rn;
4461  let Inst{4-0}   = Rt;
4462
4463  let DecoderMethod = "DecodePairLdStInstruction";
4464}
4465
4466multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4467                           Operand indextype, string asm> {
4468  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4469  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4470                                   (outs regtype:$Rt, regtype:$Rt2),
4471                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4472          Sched<[WriteLD, WriteLDHi]>;
4473
4474
4475  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4476                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4477                                                  GPR64sp:$Rn, 0)>;
4478}
4479
4480multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4481                      Operand indextype, string asm> {
4482  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4483  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4484                                   (ins regtype:$Rt, regtype:$Rt2,
4485                                        GPR64sp:$Rn, indextype:$offset),
4486                                   asm>,
4487          Sched<[WriteSTP]>;
4488
4489  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4490                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4491                                                  GPR64sp:$Rn, 0)>;
4492}
4493
4494//---
4495// Load/store exclusive
4496//---
4497
4498// True exclusive operations write to and/or read from the system's exclusive
4499// monitors, which as far as a compiler is concerned can be modelled as a
4500// random shared memory address. Hence LoadExclusive mayStore.
4501//
4502// Since these instructions have the undefined register bits set to 1 in
4503// their canonical form, we need a post encoder method to set those bits
4504// to 1 when encoding these instructions. We do this using the
4505// fixLoadStoreExclusive function. This function has template parameters:
4506//
4507// fixLoadStoreExclusive<int hasRs, int hasRt2>
4508//
4509// hasRs indicates that the instruction uses the Rs field, so we won't set
4510// it to 1 (and the same for Rt2). We don't need template parameters for
4511// the other register fields since Rt and Rn are always used.
4512//
4513let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4514class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4515                             dag oops, dag iops, string asm, string operands>
4516    : I<oops, iops, asm, operands, "", []> {
4517  let Inst{31-30} = sz;
4518  let Inst{29-24} = 0b001000;
4519  let Inst{23}    = o2;
4520  let Inst{22}    = L;
4521  let Inst{21}    = o1;
4522  let Inst{15}    = o0;
4523
4524  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4525}
4526
4527// Neither Rs nor Rt2 operands.
4528class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4529                               dag oops, dag iops, string asm, string operands>
4530    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4531  bits<5> Rt;
4532  bits<5> Rn;
4533  let Inst{20-16} = 0b11111;
4534  let Unpredictable{20-16} = 0b11111;
4535  let Inst{14-10} = 0b11111;
4536  let Unpredictable{14-10} = 0b11111;
4537  let Inst{9-5} = Rn;
4538  let Inst{4-0} = Rt;
4539
4540  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4541}
4542
4543// Simple load acquires don't set the exclusive monitor
4544let mayLoad = 1, mayStore = 0 in
4545class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4546                  RegisterClass regtype, string asm>
4547    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4548                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4549      Sched<[WriteLD]>;
4550
4551class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4552                    RegisterClass regtype, string asm>
4553    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4554                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4555      Sched<[WriteLD]>;
4556
4557class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4558                       RegisterClass regtype, string asm>
4559    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4560                             (outs regtype:$Rt, regtype:$Rt2),
4561                             (ins GPR64sp0:$Rn), asm,
4562                             "\t$Rt, $Rt2, [$Rn]">,
4563      Sched<[WriteLD, WriteLDHi]> {
4564  bits<5> Rt;
4565  bits<5> Rt2;
4566  bits<5> Rn;
4567  let Inst{14-10} = Rt2;
4568  let Inst{9-5} = Rn;
4569  let Inst{4-0} = Rt;
4570
4571  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4572}
4573
4574// Simple store release operations do not check the exclusive monitor.
4575let mayLoad = 0, mayStore = 1 in
4576class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4577                   RegisterClass regtype, string asm>
4578    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4579                               (ins regtype:$Rt, GPR64sp:$Rn),
4580                               asm, "\t$Rt, [$Rn]">,
4581      Sched<[WriteST]>;
4582
4583let mayLoad = 1, mayStore = 1 in
4584class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4585                     RegisterClass regtype, string asm>
4586    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4587                             (ins regtype:$Rt, GPR64sp0:$Rn),
4588                             asm, "\t$Ws, $Rt, [$Rn]">,
4589      Sched<[WriteSTX]> {
4590  bits<5> Ws;
4591  bits<5> Rt;
4592  bits<5> Rn;
4593  let Inst{20-16} = Ws;
4594  let Inst{9-5} = Rn;
4595  let Inst{4-0} = Rt;
4596
4597  let Constraints = "@earlyclobber $Ws";
4598  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4599}
4600
4601class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4602                         RegisterClass regtype, string asm>
4603    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4604                             (outs GPR32:$Ws),
4605                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4606                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4607      Sched<[WriteSTX]> {
4608  bits<5> Ws;
4609  bits<5> Rt;
4610  bits<5> Rt2;
4611  bits<5> Rn;
4612  let Inst{20-16} = Ws;
4613  let Inst{14-10} = Rt2;
4614  let Inst{9-5} = Rn;
4615  let Inst{4-0} = Rt;
4616
4617  let Constraints = "@earlyclobber $Ws";
4618}
4619
4620// Armv8.5-A Memory Tagging Extension
4621class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4622                 string asm_opnds, string cstr, dag oops, dag iops>
4623    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4624      Sched<[]> {
4625  bits<5> Rn;
4626
4627  let Inst{31-24} = 0b11011001;
4628  let Inst{23-22} = opc1;
4629  let Inst{21}    = 1;
4630  // Inst{20-12} defined by subclass
4631  let Inst{11-10} = opc2;
4632  let Inst{9-5}   = Rn;
4633  // Inst{4-0} defined by subclass
4634}
4635
4636class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4637                   dag oops, dag iops>
4638    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4639                  "", oops, iops> {
4640  bits<5> Rt;
4641
4642  let Inst{20-12} = 0b000000000;
4643  let Inst{4-0}   = Rt;
4644
4645  let mayLoad = Load;
4646}
4647
4648class MemTagLoad<string asm_insn, string asm_opnds>
4649    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4650                 (outs GPR64:$wback),
4651                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4652  bits<5> Rt;
4653  bits<9> offset;
4654
4655  let Inst{20-12} = offset;
4656  let Inst{4-0}   = Rt;
4657
4658  let mayLoad = 1;
4659}
4660
4661class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4662                     string asm_opnds, string cstr, dag oops, dag iops>
4663    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4664  bits<5> Rt;
4665  bits<9> offset;
4666
4667  let Inst{20-12} = offset;
4668  let Inst{4-0}   = Rt;
4669
4670  let mayStore = 1;
4671}
4672
4673multiclass MemTagStore<bits<2> opc1, string insn> {
4674  def Offset :
4675    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4676                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4677  def PreIndex :
4678    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4679                    "$Rn = $wback",
4680                    (outs GPR64sp:$wback),
4681                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4682  def PostIndex :
4683    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4684                    "$Rn = $wback",
4685                    (outs GPR64sp:$wback),
4686                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4687
4688  def : InstAlias<insn # "\t$Rt, [$Rn]",
4689                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4690}
4691
4692//---
4693// Exception generation
4694//---
4695
4696let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4697class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4698                          list<dag> pattern = []>
4699    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4700      Sched<[WriteSys]> {
4701  bits<16> imm;
4702  let Inst{31-24} = 0b11010100;
4703  let Inst{23-21} = op1;
4704  let Inst{20-5}  = imm;
4705  let Inst{4-2}   = 0b000;
4706  let Inst{1-0}   = ll;
4707}
4708
4709//---
4710// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4711//--
4712let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4713class UDFType<bits<16> opc, string asm>
4714  : I<(outs), (ins uimm16:$imm),
4715       asm, "\t$imm", "", []>,
4716    Sched<[]> {
4717  bits<16> imm;
4718  let Inst{31-16} = opc;
4719  let Inst{15-0} = imm;
4720}
4721}
4722let Predicates = [HasFPARMv8] in {
4723
4724//---
4725// Floating point to integer conversion
4726//---
4727
4728let mayRaiseFPException = 1, Uses = [FPCR] in
4729class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4730                      RegisterClass srcType, RegisterClass dstType,
4731                      string asm, list<dag> pattern>
4732    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4733         asm, "\t$Rd, $Rn", "", pattern>,
4734      Sched<[WriteFCvt]> {
4735  bits<5> Rd;
4736  bits<5> Rn;
4737  let Inst{30-29} = 0b00;
4738  let Inst{28-24} = 0b11110;
4739  let Inst{23-22} = type;
4740  let Inst{21}    = 1;
4741  let Inst{20-19} = rmode;
4742  let Inst{18-16} = opcode;
4743  let Inst{15-10} = 0;
4744  let Inst{9-5}   = Rn;
4745  let Inst{4-0}   = Rd;
4746}
4747
4748let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4749class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4750                      RegisterClass srcType, RegisterClass dstType,
4751                      Operand immType, string asm, list<dag> pattern>
4752    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4753         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4754      Sched<[WriteFCvt]> {
4755  bits<5> Rd;
4756  bits<5> Rn;
4757  bits<6> scale;
4758  let Inst{30-29} = 0b00;
4759  let Inst{28-24} = 0b11110;
4760  let Inst{23-22} = type;
4761  let Inst{21}    = 0;
4762  let Inst{20-19} = rmode;
4763  let Inst{18-16} = opcode;
4764  let Inst{15-10} = scale;
4765  let Inst{9-5}   = Rn;
4766  let Inst{4-0}   = Rd;
4767}
4768
4769multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4770           SDPatternOperator OpN> {
4771  // Unscaled half-precision to 32-bit
4772  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4773                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4774    let Inst{31} = 0; // 32-bit GPR flag
4775    let Predicates = [HasFullFP16];
4776  }
4777
4778  // Unscaled half-precision to 64-bit
4779  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4780                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4781    let Inst{31} = 1; // 64-bit GPR flag
4782    let Predicates = [HasFullFP16];
4783  }
4784
4785  // Unscaled single-precision to 32-bit
4786  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4787                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4788    let Inst{31} = 0; // 32-bit GPR flag
4789  }
4790
4791  // Unscaled single-precision to 64-bit
4792  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4793                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4794    let Inst{31} = 1; // 64-bit GPR flag
4795  }
4796
4797  // Unscaled double-precision to 32-bit
4798  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4799                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4800    let Inst{31} = 0; // 32-bit GPR flag
4801  }
4802
4803  // Unscaled double-precision to 64-bit
4804  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4805                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4806    let Inst{31} = 1; // 64-bit GPR flag
4807  }
4808}
4809
4810multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4811                             SDPatternOperator OpN> {
4812  // Scaled half-precision to 32-bit
4813  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4814                              fixedpoint_f16_i32, asm,
4815              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4816                                          fixedpoint_f16_i32:$scale)))]> {
4817    let Inst{31} = 0; // 32-bit GPR flag
4818    let scale{5} = 1;
4819    let Predicates = [HasFullFP16];
4820  }
4821
4822  // Scaled half-precision to 64-bit
4823  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4824                              fixedpoint_f16_i64, asm,
4825              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4826                                          fixedpoint_f16_i64:$scale)))]> {
4827    let Inst{31} = 1; // 64-bit GPR flag
4828    let Predicates = [HasFullFP16];
4829  }
4830
4831  // Scaled single-precision to 32-bit
4832  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4833                              fixedpoint_f32_i32, asm,
4834              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4835                                          fixedpoint_f32_i32:$scale)))]> {
4836    let Inst{31} = 0; // 32-bit GPR flag
4837    let scale{5} = 1;
4838  }
4839
4840  // Scaled single-precision to 64-bit
4841  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4842                              fixedpoint_f32_i64, asm,
4843              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4844                                          fixedpoint_f32_i64:$scale)))]> {
4845    let Inst{31} = 1; // 64-bit GPR flag
4846  }
4847
4848  // Scaled double-precision to 32-bit
4849  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4850                              fixedpoint_f64_i32, asm,
4851              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4852                                          fixedpoint_f64_i32:$scale)))]> {
4853    let Inst{31} = 0; // 32-bit GPR flag
4854    let scale{5} = 1;
4855  }
4856
4857  // Scaled double-precision to 64-bit
4858  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4859                              fixedpoint_f64_i64, asm,
4860              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4861                                          fixedpoint_f64_i64:$scale)))]> {
4862    let Inst{31} = 1; // 64-bit GPR flag
4863  }
4864}
4865
4866//---
4867// Integer to floating point conversion
4868//---
4869
4870let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4871class BaseIntegerToFP<bit isUnsigned,
4872                      RegisterClass srcType, RegisterClass dstType,
4873                      Operand immType, string asm, list<dag> pattern>
4874    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4875         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4876      Sched<[WriteFCvt]> {
4877  bits<5> Rd;
4878  bits<5> Rn;
4879  bits<6> scale;
4880  let Inst{30-24} = 0b0011110;
4881  let Inst{21-17} = 0b00001;
4882  let Inst{16}    = isUnsigned;
4883  let Inst{15-10} = scale;
4884  let Inst{9-5}   = Rn;
4885  let Inst{4-0}   = Rd;
4886}
4887
4888let mayRaiseFPException = 1, Uses = [FPCR] in
4889class BaseIntegerToFPUnscaled<bit isUnsigned,
4890                      RegisterClass srcType, RegisterClass dstType,
4891                      ValueType dvt, string asm, SDPatternOperator node>
4892    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4893         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4894      Sched<[WriteFCvt]> {
4895  bits<5> Rd;
4896  bits<5> Rn;
4897  bits<6> scale;
4898  let Inst{30-24} = 0b0011110;
4899  let Inst{21-17} = 0b10001;
4900  let Inst{16}    = isUnsigned;
4901  let Inst{15-10} = 0b000000;
4902  let Inst{9-5}   = Rn;
4903  let Inst{4-0}   = Rd;
4904}
4905
4906multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4907  // Unscaled
4908  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4909    let Inst{31} = 0; // 32-bit GPR flag
4910    let Inst{23-22} = 0b11; // 16-bit FPR flag
4911    let Predicates = [HasFullFP16];
4912  }
4913
4914  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4915    let Inst{31} = 0; // 32-bit GPR flag
4916    let Inst{23-22} = 0b00; // 32-bit FPR flag
4917  }
4918
4919  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4920    let Inst{31} = 0; // 32-bit GPR flag
4921    let Inst{23-22} = 0b01; // 64-bit FPR flag
4922  }
4923
4924  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4925    let Inst{31} = 1; // 64-bit GPR flag
4926    let Inst{23-22} = 0b11; // 16-bit FPR flag
4927    let Predicates = [HasFullFP16];
4928  }
4929
4930  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4931    let Inst{31} = 1; // 64-bit GPR flag
4932    let Inst{23-22} = 0b00; // 32-bit FPR flag
4933  }
4934
4935  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4936    let Inst{31} = 1; // 64-bit GPR flag
4937    let Inst{23-22} = 0b01; // 64-bit FPR flag
4938  }
4939
4940  // Scaled
4941  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4942                             [(set (f16 FPR16:$Rd),
4943                                   (fdiv (node GPR32:$Rn),
4944                                         fixedpoint_f16_i32:$scale))]> {
4945    let Inst{31} = 0; // 32-bit GPR flag
4946    let Inst{23-22} = 0b11; // 16-bit FPR flag
4947    let scale{5} = 1;
4948    let Predicates = [HasFullFP16];
4949  }
4950
4951  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4952                             [(set FPR32:$Rd,
4953                                   (fdiv (node GPR32:$Rn),
4954                                         fixedpoint_f32_i32:$scale))]> {
4955    let Inst{31} = 0; // 32-bit GPR flag
4956    let Inst{23-22} = 0b00; // 32-bit FPR flag
4957    let scale{5} = 1;
4958  }
4959
4960  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4961                             [(set FPR64:$Rd,
4962                                   (fdiv (node GPR32:$Rn),
4963                                         fixedpoint_f64_i32:$scale))]> {
4964    let Inst{31} = 0; // 32-bit GPR flag
4965    let Inst{23-22} = 0b01; // 64-bit FPR flag
4966    let scale{5} = 1;
4967  }
4968
4969  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4970                             [(set (f16 FPR16:$Rd),
4971                                   (fdiv (node GPR64:$Rn),
4972                                         fixedpoint_f16_i64:$scale))]> {
4973    let Inst{31} = 1; // 64-bit GPR flag
4974    let Inst{23-22} = 0b11; // 16-bit FPR flag
4975    let Predicates = [HasFullFP16];
4976  }
4977
4978  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4979                             [(set FPR32:$Rd,
4980                                   (fdiv (node GPR64:$Rn),
4981                                         fixedpoint_f32_i64:$scale))]> {
4982    let Inst{31} = 1; // 64-bit GPR flag
4983    let Inst{23-22} = 0b00; // 32-bit FPR flag
4984  }
4985
4986  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4987                             [(set FPR64:$Rd,
4988                                   (fdiv (node GPR64:$Rn),
4989                                         fixedpoint_f64_i64:$scale))]> {
4990    let Inst{31} = 1; // 64-bit GPR flag
4991    let Inst{23-22} = 0b01; // 64-bit FPR flag
4992  }
4993}
4994
4995//---
4996// Unscaled integer <-> floating point conversion (i.e. FMOV)
4997//---
4998
4999let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5000class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
5001                      RegisterClass srcType, RegisterClass dstType,
5002                      string asm>
5003    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
5004        // We use COPY_TO_REGCLASS for these bitconvert operations.
5005        // copyPhysReg() expands the resultant COPY instructions after
5006        // regalloc is done. This gives greater freedom for the allocator
5007        // and related passes (coalescing, copy propagation, et. al.) to
5008        // be more effective.
5009        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
5010      Sched<[WriteFCopy]> {
5011  bits<5> Rd;
5012  bits<5> Rn;
5013  let Inst{30-24} = 0b0011110;
5014  let Inst{21}    = 1;
5015  let Inst{20-19} = rmode;
5016  let Inst{18-16} = opcode;
5017  let Inst{15-10} = 0b000000;
5018  let Inst{9-5}   = Rn;
5019  let Inst{4-0}   = Rd;
5020}
5021
5022let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5023class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
5024                     RegisterClass srcType, RegisterOperand dstType, string asm,
5025                     string kind>
5026    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5027        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
5028      Sched<[WriteFCopy]> {
5029  bits<5> Rd;
5030  bits<5> Rn;
5031  let Inst{30-23} = 0b00111101;
5032  let Inst{21}    = 1;
5033  let Inst{20-19} = rmode;
5034  let Inst{18-16} = opcode;
5035  let Inst{15-10} = 0b000000;
5036  let Inst{9-5}   = Rn;
5037  let Inst{4-0}   = Rd;
5038
5039  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5040}
5041
5042let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5043class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
5044                     RegisterOperand srcType, RegisterClass dstType, string asm,
5045                     string kind>
5046    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5047        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
5048      Sched<[WriteFCopy]> {
5049  bits<5> Rd;
5050  bits<5> Rn;
5051  let Inst{30-23} = 0b00111101;
5052  let Inst{21}    = 1;
5053  let Inst{20-19} = rmode;
5054  let Inst{18-16} = opcode;
5055  let Inst{15-10} = 0b000000;
5056  let Inst{9-5}   = Rn;
5057  let Inst{4-0}   = Rd;
5058
5059  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5060}
5061
5062
5063multiclass UnscaledConversion<string asm> {
5064  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
5065    let Inst{31} = 0; // 32-bit GPR flag
5066    let Inst{23-22} = 0b11; // 16-bit FPR flag
5067    let Predicates = [HasFullFP16];
5068  }
5069
5070  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
5071    let Inst{31} = 1; // 64-bit GPR flag
5072    let Inst{23-22} = 0b11; // 16-bit FPR flag
5073    let Predicates = [HasFullFP16];
5074  }
5075
5076  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
5077    let Inst{31} = 0; // 32-bit GPR flag
5078    let Inst{23-22} = 0b00; // 32-bit FPR flag
5079  }
5080
5081  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
5082    let Inst{31} = 1; // 64-bit GPR flag
5083    let Inst{23-22} = 0b01; // 64-bit FPR flag
5084  }
5085
5086  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
5087    let Inst{31} = 0; // 32-bit GPR flag
5088    let Inst{23-22} = 0b11; // 16-bit FPR flag
5089    let Predicates = [HasFullFP16];
5090  }
5091
5092  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
5093    let Inst{31} = 1; // 64-bit GPR flag
5094    let Inst{23-22} = 0b11; // 16-bit FPR flag
5095    let Predicates = [HasFullFP16];
5096  }
5097
5098  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
5099    let Inst{31} = 0; // 32-bit GPR flag
5100    let Inst{23-22} = 0b00; // 32-bit FPR flag
5101  }
5102
5103  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
5104    let Inst{31} = 1; // 64-bit GPR flag
5105    let Inst{23-22} = 0b01; // 64-bit FPR flag
5106  }
5107
5108  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
5109                                             asm, ".d"> {
5110    let Inst{31} = 1;
5111    let Inst{22} = 0;
5112  }
5113
5114  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
5115                                               asm, ".d"> {
5116    let Inst{31} = 1;
5117    let Inst{22} = 0;
5118  }
5119}
5120
5121//---
5122// Floating point conversion
5123//---
5124
5125let mayRaiseFPException = 1, Uses = [FPCR] in
5126class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
5127                       RegisterClass srcType, string asm, list<dag> pattern>
5128    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
5129      Sched<[WriteFCvt]> {
5130  bits<5> Rd;
5131  bits<5> Rn;
5132  let Inst{31-24} = 0b00011110;
5133  let Inst{23-22} = type;
5134  let Inst{21-17} = 0b10001;
5135  let Inst{16-15} = opcode;
5136  let Inst{14-10} = 0b10000;
5137  let Inst{9-5}   = Rn;
5138  let Inst{4-0}   = Rd;
5139}
5140
5141multiclass FPConversion<string asm> {
5142  // Double-precision to Half-precision
5143  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
5144                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
5145
5146  // Double-precision to Single-precision
5147  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
5148                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5149
5150  // Half-precision to Double-precision
5151  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5152                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5153
5154  // Half-precision to Single-precision
5155  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5156                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5157
5158  // Single-precision to Double-precision
5159  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5160                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5161
5162  // Single-precision to Half-precision
5163  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5164                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5165}
5166
5167//---
5168// Single operand floating point data processing
5169//---
5170
5171let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5172class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5173                              ValueType vt, string asm, SDPatternOperator node>
5174    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5175         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5176      Sched<[WriteF]> {
5177  bits<5> Rd;
5178  bits<5> Rn;
5179  let Inst{31-24} = 0b00011110;
5180  let Inst{21}    = 0b1;
5181  let Inst{20-15} = opcode;
5182  let Inst{14-10} = 0b10000;
5183  let Inst{9-5}   = Rn;
5184  let Inst{4-0}   = Rd;
5185}
5186
5187multiclass SingleOperandFPData<bits<4> opcode, string asm,
5188                               SDPatternOperator node = null_frag,
5189                               int fpexceptions = 1> {
5190  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
5191  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5192    let Inst{23-22} = 0b11; // 16-bit size flag
5193    let Predicates = [HasFullFP16];
5194  }
5195
5196  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5197    let Inst{23-22} = 0b00; // 32-bit size flag
5198  }
5199
5200  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5201    let Inst{23-22} = 0b01; // 64-bit size flag
5202  }
5203  }
5204}
5205
5206multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5207                                       SDPatternOperator node = null_frag>
5208    : SingleOperandFPData<opcode, asm, node, 0>;
5209
5210let mayRaiseFPException = 1, Uses = [FPCR] in
5211multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5212                  SDPatternOperator node = null_frag>{
5213
5214  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5215    let Inst{23-22} = 0b00; // 32-bit registers
5216  }
5217
5218  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5219    let Inst{23-22} = 0b01; // 64-bit registers
5220  }
5221}
5222
5223// FRInt[32|64][Z|N] instructions
5224multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5225      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5226
5227//---
5228// Two operand floating point data processing
5229//---
5230
5231let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5232class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5233                           string asm, list<dag> pat>
5234    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5235         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5236      Sched<[WriteF]> {
5237  bits<5> Rd;
5238  bits<5> Rn;
5239  bits<5> Rm;
5240  let Inst{31-24} = 0b00011110;
5241  let Inst{21}    = 1;
5242  let Inst{20-16} = Rm;
5243  let Inst{15-12} = opcode;
5244  let Inst{11-10} = 0b10;
5245  let Inst{9-5}   = Rn;
5246  let Inst{4-0}   = Rd;
5247}
5248
5249multiclass TwoOperandFPData<bits<4> opcode, string asm,
5250                            SDPatternOperator node = null_frag> {
5251  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5252                         [(set (f16 FPR16:$Rd),
5253                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5254    let Inst{23-22} = 0b11; // 16-bit size flag
5255    let Predicates = [HasFullFP16];
5256  }
5257
5258  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5259                         [(set (f32 FPR32:$Rd),
5260                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5261    let Inst{23-22} = 0b00; // 32-bit size flag
5262  }
5263
5264  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5265                         [(set (f64 FPR64:$Rd),
5266                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5267    let Inst{23-22} = 0b01; // 64-bit size flag
5268  }
5269}
5270
5271multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5272                               SDPatternOperator node> {
5273  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5274                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5275    let Inst{23-22} = 0b11; // 16-bit size flag
5276    let Predicates = [HasFullFP16];
5277  }
5278
5279  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5280                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5281    let Inst{23-22} = 0b00; // 32-bit size flag
5282  }
5283
5284  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5285                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5286    let Inst{23-22} = 0b01; // 64-bit size flag
5287  }
5288}
5289
5290
5291//---
5292// Three operand floating point data processing
5293//---
5294
5295let mayRaiseFPException = 1, Uses = [FPCR] in
5296class BaseThreeOperandFPData<bit isNegated, bit isSub,
5297                             RegisterClass regtype, string asm, list<dag> pat>
5298    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5299         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5300      Sched<[WriteFMul]> {
5301  bits<5> Rd;
5302  bits<5> Rn;
5303  bits<5> Rm;
5304  bits<5> Ra;
5305  let Inst{31-24} = 0b00011111;
5306  let Inst{21}    = isNegated;
5307  let Inst{20-16} = Rm;
5308  let Inst{15}    = isSub;
5309  let Inst{14-10} = Ra;
5310  let Inst{9-5}   = Rn;
5311  let Inst{4-0}   = Rd;
5312}
5313
5314multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5315                              SDPatternOperator node> {
5316  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5317            [(set (f16 FPR16:$Rd),
5318                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5319    let Inst{23-22} = 0b11; // 16-bit size flag
5320    let Predicates = [HasFullFP16];
5321  }
5322
5323  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5324            [(set FPR32:$Rd,
5325                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5326    let Inst{23-22} = 0b00; // 32-bit size flag
5327  }
5328
5329  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5330            [(set FPR64:$Rd,
5331                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5332    let Inst{23-22} = 0b01; // 64-bit size flag
5333  }
5334}
5335
5336//---
5337// Floating point data comparisons
5338//---
5339
5340let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5341class BaseOneOperandFPComparison<bit signalAllNans,
5342                                 RegisterClass regtype, string asm,
5343                                 list<dag> pat>
5344    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5345      Sched<[WriteFCmp]> {
5346  bits<5> Rn;
5347  let Inst{31-24} = 0b00011110;
5348  let Inst{21}    = 1;
5349
5350  let Inst{15-10} = 0b001000;
5351  let Inst{9-5}   = Rn;
5352  let Inst{4}     = signalAllNans;
5353  let Inst{3-0}   = 0b1000;
5354
5355  // Rm should be 0b00000 canonically, but we need to accept any value.
5356  let PostEncoderMethod = "fixOneOperandFPComparison";
5357}
5358
5359let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5360class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5361                                string asm, list<dag> pat>
5362    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5363      Sched<[WriteFCmp]> {
5364  bits<5> Rm;
5365  bits<5> Rn;
5366  let Inst{31-24} = 0b00011110;
5367  let Inst{21}    = 1;
5368  let Inst{20-16} = Rm;
5369  let Inst{15-10} = 0b001000;
5370  let Inst{9-5}   = Rn;
5371  let Inst{4}     = signalAllNans;
5372  let Inst{3-0}   = 0b0000;
5373}
5374
5375multiclass FPComparison<bit signalAllNans, string asm,
5376                        SDPatternOperator OpNode = null_frag> {
5377  let Defs = [NZCV] in {
5378  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5379      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5380    let Inst{23-22} = 0b11;
5381    let Predicates = [HasFullFP16];
5382  }
5383
5384  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5385      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5386    let Inst{23-22} = 0b11;
5387    let Predicates = [HasFullFP16];
5388  }
5389
5390  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5391      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5392    let Inst{23-22} = 0b00;
5393  }
5394
5395  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5396      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5397    let Inst{23-22} = 0b00;
5398  }
5399
5400  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5401      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5402    let Inst{23-22} = 0b01;
5403  }
5404
5405  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5406      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5407    let Inst{23-22} = 0b01;
5408  }
5409  } // Defs = [NZCV]
5410}
5411
5412//---
5413// Floating point conditional comparisons
5414//---
5415
5416let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5417class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5418                           string mnemonic, list<dag> pat>
5419    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5420         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5421      Sched<[WriteFCmp]> {
5422  let Uses = [NZCV];
5423  let Defs = [NZCV];
5424
5425  bits<5> Rn;
5426  bits<5> Rm;
5427  bits<4> nzcv;
5428  bits<4> cond;
5429
5430  let Inst{31-24} = 0b00011110;
5431  let Inst{21}    = 1;
5432  let Inst{20-16} = Rm;
5433  let Inst{15-12} = cond;
5434  let Inst{11-10} = 0b01;
5435  let Inst{9-5}   = Rn;
5436  let Inst{4}     = signalAllNans;
5437  let Inst{3-0}   = nzcv;
5438}
5439
5440multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5441                            SDPatternOperator OpNode = null_frag> {
5442  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5443      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5444                          (i32 imm:$cond), NZCV))]> {
5445    let Inst{23-22} = 0b11;
5446    let Predicates = [HasFullFP16];
5447  }
5448
5449  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5450      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5451                          (i32 imm:$cond), NZCV))]> {
5452    let Inst{23-22} = 0b00;
5453  }
5454
5455  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5456      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5457                          (i32 imm:$cond), NZCV))]> {
5458    let Inst{23-22} = 0b01;
5459  }
5460}
5461
5462//---
5463// Floating point conditional select
5464//---
5465
5466class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5467    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5468         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5469         [(set regtype:$Rd,
5470               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5471                          (i32 imm:$cond), NZCV))]>,
5472      Sched<[WriteF]> {
5473  bits<5> Rd;
5474  bits<5> Rn;
5475  bits<5> Rm;
5476  bits<4> cond;
5477
5478  let Inst{31-24} = 0b00011110;
5479  let Inst{21}    = 1;
5480  let Inst{20-16} = Rm;
5481  let Inst{15-12} = cond;
5482  let Inst{11-10} = 0b11;
5483  let Inst{9-5}   = Rn;
5484  let Inst{4-0}   = Rd;
5485}
5486
5487multiclass FPCondSelect<string asm> {
5488  let Uses = [NZCV] in {
5489  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5490    let Inst{23-22} = 0b11;
5491    let Predicates = [HasFullFP16];
5492  }
5493
5494  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5495    let Inst{23-22} = 0b00;
5496  }
5497
5498  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5499    let Inst{23-22} = 0b01;
5500  }
5501  } // Uses = [NZCV]
5502}
5503
5504//---
5505// Floating move immediate
5506//---
5507
5508class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5509  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5510      [(set regtype:$Rd, fpimmtype:$imm)]>,
5511    Sched<[WriteFImm]> {
5512  bits<5> Rd;
5513  bits<8> imm;
5514  let Inst{31-24} = 0b00011110;
5515  let Inst{21}    = 1;
5516  let Inst{20-13} = imm;
5517  let Inst{12-5}  = 0b10000000;
5518  let Inst{4-0}   = Rd;
5519}
5520
5521multiclass FPMoveImmediate<string asm> {
5522  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5523    let Inst{23-22} = 0b11;
5524    let Predicates = [HasFullFP16];
5525  }
5526
5527  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5528    let Inst{23-22} = 0b00;
5529  }
5530
5531  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5532    let Inst{23-22} = 0b01;
5533  }
5534}
5535} // end of 'let Predicates = [HasFPARMv8]'
5536
5537//----------------------------------------------------------------------------
5538// AdvSIMD
5539//----------------------------------------------------------------------------
5540
5541let Predicates = [HasNEON] in {
5542
5543//----------------------------------------------------------------------------
5544// AdvSIMD three register vector instructions
5545//----------------------------------------------------------------------------
5546
5547let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5548class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5549                        RegisterOperand regtype, string asm, string kind,
5550                        list<dag> pattern>
5551  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5552      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5553      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5554    Sched<[!if(Q, WriteVq, WriteVd)]> {
5555  bits<5> Rd;
5556  bits<5> Rn;
5557  bits<5> Rm;
5558  let Inst{31}    = 0;
5559  let Inst{30}    = Q;
5560  let Inst{29}    = U;
5561  let Inst{28-24} = 0b01110;
5562  let Inst{23-21} = size;
5563  let Inst{20-16} = Rm;
5564  let Inst{15-11} = opcode;
5565  let Inst{10}    = 1;
5566  let Inst{9-5}   = Rn;
5567  let Inst{4-0}   = Rd;
5568}
5569
5570let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5571class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5572                        RegisterOperand regtype, string asm, string kind,
5573                        list<dag> pattern>
5574  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5575      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5576      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5577    Sched<[!if(Q, WriteVq, WriteVd)]> {
5578  bits<5> Rd;
5579  bits<5> Rn;
5580  bits<5> Rm;
5581  let Inst{31}    = 0;
5582  let Inst{30}    = Q;
5583  let Inst{29}    = U;
5584  let Inst{28-24} = 0b01110;
5585  let Inst{23-21} = size;
5586  let Inst{20-16} = Rm;
5587  let Inst{15-11} = opcode;
5588  let Inst{10}    = 1;
5589  let Inst{9-5}   = Rn;
5590  let Inst{4-0}   = Rd;
5591}
5592
5593let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5594class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5595  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5596    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5597
5598multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5599  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5600             [(set (v8i8 V64:$dst),
5601                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5602  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5603             [(set (v16i8 V128:$dst),
5604                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5605                           (v16i8 V128:$Rm)))]>;
5606
5607  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5608                           (v4i16 V64:$RHS))),
5609          (!cast<Instruction>(NAME#"v8i8")
5610            V64:$LHS, V64:$MHS, V64:$RHS)>;
5611  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5612                           (v2i32 V64:$RHS))),
5613          (!cast<Instruction>(NAME#"v8i8")
5614            V64:$LHS, V64:$MHS, V64:$RHS)>;
5615  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5616                           (v1i64 V64:$RHS))),
5617          (!cast<Instruction>(NAME#"v8i8")
5618            V64:$LHS, V64:$MHS, V64:$RHS)>;
5619
5620  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5621                           (v8i16 V128:$RHS))),
5622      (!cast<Instruction>(NAME#"v16i8")
5623        V128:$LHS, V128:$MHS, V128:$RHS)>;
5624  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5625                           (v4i32 V128:$RHS))),
5626      (!cast<Instruction>(NAME#"v16i8")
5627        V128:$LHS, V128:$MHS, V128:$RHS)>;
5628  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5629                           (v2i64 V128:$RHS))),
5630      (!cast<Instruction>(NAME#"v16i8")
5631        V128:$LHS, V128:$MHS, V128:$RHS)>;
5632}
5633
5634// All operand sizes distinguished in the encoding.
5635multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5636                               SDPatternOperator OpNode> {
5637  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5638                                      asm, ".8b",
5639         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5640  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5641                                      asm, ".16b",
5642         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5643  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5644                                      asm, ".4h",
5645         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5646  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5647                                      asm, ".8h",
5648         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5649  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5650                                      asm, ".2s",
5651         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5652  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5653                                      asm, ".4s",
5654         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5655  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5656                                      asm, ".2d",
5657         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5658}
5659
5660multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5661  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5662          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5663  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5664          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5665  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5666          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5667
5668  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5669          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5670  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5671          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5672  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5673          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5674  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5675          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5676}
5677
5678// As above, but D sized elements unsupported.
5679multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5680                                  SDPatternOperator OpNode> {
5681  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5682                                      asm, ".8b",
5683        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5684  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5685                                      asm, ".16b",
5686        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5687  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5688                                      asm, ".4h",
5689        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5690  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5691                                      asm, ".8h",
5692        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5693  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5694                                      asm, ".2s",
5695        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5696  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5697                                      asm, ".4s",
5698        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5699}
5700
5701multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5702                                  SDPatternOperator OpNode> {
5703  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5704                                      asm, ".8b",
5705      [(set (v8i8 V64:$dst),
5706            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5707  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5708                                      asm, ".16b",
5709      [(set (v16i8 V128:$dst),
5710            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5711  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5712                                      asm, ".4h",
5713      [(set (v4i16 V64:$dst),
5714            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5715  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5716                                      asm, ".8h",
5717      [(set (v8i16 V128:$dst),
5718            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5719  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5720                                      asm, ".2s",
5721      [(set (v2i32 V64:$dst),
5722            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5723  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5724                                      asm, ".4s",
5725      [(set (v4i32 V128:$dst),
5726            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5727}
5728
5729// As above, but only B sized elements supported.
5730multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5731                                SDPatternOperator OpNode> {
5732  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5733                                      asm, ".8b",
5734    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5735  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5736                                      asm, ".16b",
5737    [(set (v16i8 V128:$Rd),
5738          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5739}
5740
5741// As above, but only floating point elements supported.
5742let mayRaiseFPException = 1, Uses = [FPCR] in
5743multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5744                                 string asm, SDPatternOperator OpNode> {
5745  let Predicates = [HasNEON, HasFullFP16] in {
5746  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5747                                      asm, ".4h",
5748        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5749  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5750                                      asm, ".8h",
5751        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5752  } // Predicates = [HasNEON, HasFullFP16]
5753  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5754                                      asm, ".2s",
5755        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5756  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5757                                      asm, ".4s",
5758        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5759  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5760                                      asm, ".2d",
5761        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5762}
5763
5764let mayRaiseFPException = 1, Uses = [FPCR] in
5765multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5766                                    string asm,
5767                                    SDPatternOperator OpNode> {
5768  let Predicates = [HasNEON, HasFullFP16] in {
5769  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5770                                      asm, ".4h",
5771        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5772  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5773                                      asm, ".8h",
5774        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5775  } // Predicates = [HasNEON, HasFullFP16]
5776  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5777                                      asm, ".2s",
5778        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5779  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5780                                      asm, ".4s",
5781        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5782  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5783                                      asm, ".2d",
5784        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5785}
5786
5787let mayRaiseFPException = 1, Uses = [FPCR] in
5788multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5789                                 string asm, SDPatternOperator OpNode> {
5790  let Predicates = [HasNEON, HasFullFP16] in {
5791  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5792                                      asm, ".4h",
5793     [(set (v4f16 V64:$dst),
5794           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5795  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5796                                      asm, ".8h",
5797     [(set (v8f16 V128:$dst),
5798           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5799  } // Predicates = [HasNEON, HasFullFP16]
5800  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5801                                      asm, ".2s",
5802     [(set (v2f32 V64:$dst),
5803           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5804  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5805                                      asm, ".4s",
5806     [(set (v4f32 V128:$dst),
5807           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5808  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5809                                      asm, ".2d",
5810     [(set (v2f64 V128:$dst),
5811           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5812}
5813
5814// As above, but D and B sized elements unsupported.
5815let mayRaiseFPException = 1, Uses = [FPCR] in
5816multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5817                                SDPatternOperator OpNode> {
5818  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5819                                      asm, ".4h",
5820        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5821  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5822                                      asm, ".8h",
5823        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5824  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5825                                      asm, ".2s",
5826        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5827  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5828                                      asm, ".4s",
5829        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5830}
5831
5832// Logical three vector ops share opcode bits, and only use B sized elements.
5833multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5834                                  SDPatternOperator OpNode = null_frag> {
5835  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5836                                     asm, ".8b",
5837                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5838  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5839                                     asm, ".16b",
5840                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5841
5842  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5843          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5844  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5845          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5846  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5847          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5848
5849  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5850      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5851  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5852      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5853  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5854      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5855}
5856
5857multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5858                                  string asm, SDPatternOperator OpNode = null_frag> {
5859  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5860                                     asm, ".8b",
5861             [(set (v8i8 V64:$dst),
5862                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5863  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5864                                     asm, ".16b",
5865             [(set (v16i8 V128:$dst),
5866                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5867                           (v16i8 V128:$Rm)))]>;
5868
5869  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5870                           (v4i16 V64:$RHS))),
5871          (!cast<Instruction>(NAME#"v8i8")
5872            V64:$LHS, V64:$MHS, V64:$RHS)>;
5873  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5874                           (v2i32 V64:$RHS))),
5875          (!cast<Instruction>(NAME#"v8i8")
5876            V64:$LHS, V64:$MHS, V64:$RHS)>;
5877  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5878                           (v1i64 V64:$RHS))),
5879          (!cast<Instruction>(NAME#"v8i8")
5880            V64:$LHS, V64:$MHS, V64:$RHS)>;
5881
5882  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5883                           (v8i16 V128:$RHS))),
5884      (!cast<Instruction>(NAME#"v16i8")
5885        V128:$LHS, V128:$MHS, V128:$RHS)>;
5886  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5887                           (v4i32 V128:$RHS))),
5888      (!cast<Instruction>(NAME#"v16i8")
5889        V128:$LHS, V128:$MHS, V128:$RHS)>;
5890  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5891                           (v2i64 V128:$RHS))),
5892      (!cast<Instruction>(NAME#"v16i8")
5893        V128:$LHS, V128:$MHS, V128:$RHS)>;
5894}
5895
5896// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5897// bytes from S-sized elements.
5898class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5899                                 string kind2, RegisterOperand RegType,
5900                                 ValueType AccumType, ValueType InputType,
5901                                 SDPatternOperator OpNode> :
5902        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5903        [(set (AccumType RegType:$dst),
5904              (OpNode (AccumType RegType:$Rd),
5905                      (InputType RegType:$Rn),
5906                      (InputType RegType:$Rm)))]> {
5907  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5908}
5909
5910multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5911  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5912                                         v2i32, v8i8, OpNode>;
5913  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5914                                         v4i32, v16i8, OpNode>;
5915}
5916
5917// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5918// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5919// 8H to 4S, when Q=1).
5920let mayRaiseFPException = 1, Uses = [FPCR] in
5921class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5922                                 string kind2, RegisterOperand RegType,
5923                                 ValueType AccumType, ValueType InputType,
5924                                 SDPatternOperator OpNode> :
5925        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5926		[(set (AccumType RegType:$dst),
5927              (OpNode (AccumType RegType:$Rd),
5928                      (InputType RegType:$Rn),
5929                      (InputType RegType:$Rm)))]> {
5930  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5931  let Inst{13} = b13;
5932}
5933
5934multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5935                                  SDPatternOperator OpNode> {
5936  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5937                                         v2f32, v4f16, OpNode>;
5938  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5939                                         v4f32, v8f16, OpNode>;
5940}
5941
5942
5943//----------------------------------------------------------------------------
5944// AdvSIMD two register vector instructions.
5945//----------------------------------------------------------------------------
5946
5947let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5948class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5949                            bits<2> size2, RegisterOperand regtype, string asm,
5950                            string dstkind, string srckind, list<dag> pattern>
5951  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5952      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5953      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5954    Sched<[!if(Q, WriteVq, WriteVd)]> {
5955  bits<5> Rd;
5956  bits<5> Rn;
5957  let Inst{31}    = 0;
5958  let Inst{30}    = Q;
5959  let Inst{29}    = U;
5960  let Inst{28-24} = 0b01110;
5961  let Inst{23-22} = size;
5962  let Inst{21} = 0b1;
5963  let Inst{20-19} = size2;
5964  let Inst{18-17} = 0b00;
5965  let Inst{16-12} = opcode;
5966  let Inst{11-10} = 0b10;
5967  let Inst{9-5}   = Rn;
5968  let Inst{4-0}   = Rd;
5969}
5970
5971let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5972class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5973                                bits<2> size2, RegisterOperand regtype,
5974                                string asm, string dstkind, string srckind,
5975                                list<dag> pattern>
5976  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5977      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5978      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5979    Sched<[!if(Q, WriteVq, WriteVd)]> {
5980  bits<5> Rd;
5981  bits<5> Rn;
5982  let Inst{31}    = 0;
5983  let Inst{30}    = Q;
5984  let Inst{29}    = U;
5985  let Inst{28-24} = 0b01110;
5986  let Inst{23-22} = size;
5987  let Inst{21} = 0b1;
5988  let Inst{20-19} = size2;
5989  let Inst{18-17} = 0b00;
5990  let Inst{16-12} = opcode;
5991  let Inst{11-10} = 0b10;
5992  let Inst{9-5}   = Rn;
5993  let Inst{4-0}   = Rd;
5994}
5995
5996// Supports B, H, and S element sizes.
5997multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5998                            SDPatternOperator OpNode> {
5999  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6000                                      asm, ".8b", ".8b",
6001                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6002  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6003                                      asm, ".16b", ".16b",
6004                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6005  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6006                                      asm, ".4h", ".4h",
6007                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6008  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6009                                      asm, ".8h", ".8h",
6010                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6011  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6012                                      asm, ".2s", ".2s",
6013                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6014  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6015                                      asm, ".4s", ".4s",
6016                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6017}
6018
6019class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
6020                            RegisterOperand regtype, string asm, string dstkind,
6021                            string srckind, string amount>
6022  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
6023      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
6024      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
6025    Sched<[WriteVq]> {
6026  bits<5> Rd;
6027  bits<5> Rn;
6028  let Inst{31}    = 0;
6029  let Inst{30}    = Q;
6030  let Inst{29-24} = 0b101110;
6031  let Inst{23-22} = size;
6032  let Inst{21-10} = 0b100001001110;
6033  let Inst{9-5}   = Rn;
6034  let Inst{4-0}   = Rd;
6035}
6036
6037multiclass SIMDVectorLShiftLongBySizeBHS {
6038  let hasSideEffects = 0 in {
6039  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
6040                                             "shll", ".8h",  ".8b", "8">;
6041  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
6042                                             "shll2", ".8h", ".16b", "8">;
6043  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
6044                                             "shll", ".4s",  ".4h", "16">;
6045  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
6046                                             "shll2", ".4s", ".8h", "16">;
6047  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
6048                                             "shll", ".2d",  ".2s", "32">;
6049  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
6050                                             "shll2", ".2d", ".4s", "32">;
6051  }
6052}
6053
6054// Supports all element sizes.
6055multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
6056                             SDPatternOperator OpNode> {
6057  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6058                                      asm, ".4h", ".8b",
6059               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6060  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6061                                      asm, ".8h", ".16b",
6062               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6063  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6064                                      asm, ".2s", ".4h",
6065               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6066  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6067                                      asm, ".4s", ".8h",
6068               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6069  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6070                                      asm, ".1d", ".2s",
6071               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6072  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6073                                      asm, ".2d", ".4s",
6074               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6075}
6076
6077multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
6078                                 SDPatternOperator OpNode> {
6079  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6080                                          asm, ".4h", ".8b",
6081      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
6082                                      (v8i8 V64:$Rn)))]>;
6083  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6084                                          asm, ".8h", ".16b",
6085      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
6086                                      (v16i8 V128:$Rn)))]>;
6087  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6088                                          asm, ".2s", ".4h",
6089      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
6090                                      (v4i16 V64:$Rn)))]>;
6091  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6092                                          asm, ".4s", ".8h",
6093      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
6094                                      (v8i16 V128:$Rn)))]>;
6095  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6096                                          asm, ".1d", ".2s",
6097      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
6098                                      (v2i32 V64:$Rn)))]>;
6099  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6100                                          asm, ".2d", ".4s",
6101      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
6102                                      (v4i32 V128:$Rn)))]>;
6103}
6104
6105// Supports all element sizes, except 1xD.
6106multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
6107                                  SDPatternOperator OpNode> {
6108  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6109                                    asm, ".8b", ".8b",
6110    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
6111  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6112                                    asm, ".16b", ".16b",
6113    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
6114  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6115                                    asm, ".4h", ".4h",
6116    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
6117  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6118                                    asm, ".8h", ".8h",
6119    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
6120  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6121                                    asm, ".2s", ".2s",
6122    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
6123  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6124                                    asm, ".4s", ".4s",
6125    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
6126  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
6127                                    asm, ".2d", ".2d",
6128    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
6129}
6130
6131multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
6132                             SDPatternOperator OpNode = null_frag> {
6133  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6134                                asm, ".8b", ".8b",
6135    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6136  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6137                                asm, ".16b", ".16b",
6138    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6139  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6140                                asm, ".4h", ".4h",
6141    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6142  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6143                                asm, ".8h", ".8h",
6144    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6145  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6146                                asm, ".2s", ".2s",
6147    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6148  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6149                                asm, ".4s", ".4s",
6150    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6151  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6152                                asm, ".2d", ".2d",
6153    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6154}
6155
6156
6157// Supports only B element sizes.
6158multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6159                          SDPatternOperator OpNode> {
6160  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6161                                asm, ".8b", ".8b",
6162                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6163  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6164                                asm, ".16b", ".16b",
6165                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6166
6167}
6168
6169// Supports only B and H element sizes.
6170multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6171                                SDPatternOperator OpNode> {
6172  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6173                                asm, ".8b", ".8b",
6174                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6175  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6176                                asm, ".16b", ".16b",
6177                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6178  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6179                                asm, ".4h", ".4h",
6180                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6181  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6182                                asm, ".8h", ".8h",
6183                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6184}
6185
6186// Supports H, S and D element sizes, uses high bit of the size field
6187// as an extra opcode bit.
6188multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6189                           SDPatternOperator OpNode,
6190                           int fpexceptions = 1> {
6191  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
6192  let Predicates = [HasNEON, HasFullFP16] in {
6193  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6194                                asm, ".4h", ".4h",
6195                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6196  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6197                                asm, ".8h", ".8h",
6198                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6199  } // Predicates = [HasNEON, HasFullFP16]
6200  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6201                                asm, ".2s", ".2s",
6202                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6203  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6204                                asm, ".4s", ".4s",
6205                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6206  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6207                                asm, ".2d", ".2d",
6208                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6209  }
6210}
6211
6212multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6213                                      SDPatternOperator OpNode>
6214    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6215
6216// Supports only S and D element sizes
6217let mayRaiseFPException = 1, Uses = [FPCR] in
6218multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6219                           SDPatternOperator OpNode = null_frag> {
6220
6221  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6222                                asm, ".2s", ".2s",
6223                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6224  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6225                                asm, ".4s", ".4s",
6226                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6227  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6228                                asm, ".2d", ".2d",
6229                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6230}
6231
6232multiclass FRIntNNTVector<bit U, bit op, string asm,
6233                          SDPatternOperator OpNode = null_frag> :
6234           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6235
6236// Supports only S element size.
6237multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6238                           SDPatternOperator OpNode> {
6239  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6240                                asm, ".2s", ".2s",
6241                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6242  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6243                                asm, ".4s", ".4s",
6244                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6245}
6246
6247let mayRaiseFPException = 1, Uses = [FPCR] in
6248multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6249                           SDPatternOperator OpNode> {
6250  let Predicates = [HasNEON, HasFullFP16] in {
6251  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6252                                asm, ".4h", ".4h",
6253                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6254  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6255                                asm, ".8h", ".8h",
6256                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6257  } // Predicates = [HasNEON, HasFullFP16]
6258  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6259                                asm, ".2s", ".2s",
6260                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6261  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6262                                asm, ".4s", ".4s",
6263                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6264  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6265                                asm, ".2d", ".2d",
6266                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6267}
6268
6269let mayRaiseFPException = 1, Uses = [FPCR] in
6270multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6271                           SDPatternOperator OpNode> {
6272  let Predicates = [HasNEON, HasFullFP16] in {
6273  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6274                                asm, ".4h", ".4h",
6275                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6276  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6277                                asm, ".8h", ".8h",
6278                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6279  } // Predicates = [HasNEON, HasFullFP16]
6280  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6281                                asm, ".2s", ".2s",
6282                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6283  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6284                                asm, ".4s", ".4s",
6285                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6286  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6287                                asm, ".2d", ".2d",
6288                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6289}
6290
6291let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6292class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6293                           RegisterOperand inreg, RegisterOperand outreg,
6294                           string asm, string outkind, string inkind,
6295                           list<dag> pattern>
6296  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6297      "{\t$Rd" # outkind # ", $Rn" # inkind #
6298      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6299    Sched<[WriteVq]> {
6300  bits<5> Rd;
6301  bits<5> Rn;
6302  let Inst{31}    = 0;
6303  let Inst{30}    = Q;
6304  let Inst{29}    = U;
6305  let Inst{28-24} = 0b01110;
6306  let Inst{23-22} = size;
6307  let Inst{21-17} = 0b10000;
6308  let Inst{16-12} = opcode;
6309  let Inst{11-10} = 0b10;
6310  let Inst{9-5}   = Rn;
6311  let Inst{4-0}   = Rd;
6312}
6313
6314let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6315class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6316                           RegisterOperand inreg, RegisterOperand outreg,
6317                           string asm, string outkind, string inkind,
6318                           list<dag> pattern>
6319  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6320      "{\t$Rd" # outkind # ", $Rn" # inkind #
6321      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6322    Sched<[WriteVq]> {
6323  bits<5> Rd;
6324  bits<5> Rn;
6325  let Inst{31}    = 0;
6326  let Inst{30}    = Q;
6327  let Inst{29}    = U;
6328  let Inst{28-24} = 0b01110;
6329  let Inst{23-22} = size;
6330  let Inst{21-17} = 0b10000;
6331  let Inst{16-12} = opcode;
6332  let Inst{11-10} = 0b10;
6333  let Inst{9-5}   = Rn;
6334  let Inst{4-0}   = Rd;
6335}
6336
6337multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6338                              SDPatternOperator OpNode> {
6339  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6340                                      asm, ".8b", ".8h",
6341        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6342  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6343                                      asm#"2", ".16b", ".8h", []>;
6344  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6345                                      asm, ".4h", ".4s",
6346        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6347  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6348                                      asm#"2", ".8h", ".4s", []>;
6349  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6350                                      asm, ".2s", ".2d",
6351        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6352  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6353                                      asm#"2", ".4s", ".2d", []>;
6354
6355  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6356            (!cast<Instruction>(NAME # "v16i8")
6357                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6358  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6359            (!cast<Instruction>(NAME # "v8i16")
6360                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6361  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6362            (!cast<Instruction>(NAME # "v4i32")
6363                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6364}
6365
6366class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6367                           bits<5> opcode, RegisterOperand regtype, string asm,
6368                           string kind, string zero, ValueType dty,
6369                           ValueType sty, SDNode OpNode>
6370  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6371      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6372      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6373      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6374    Sched<[!if(Q, WriteVq, WriteVd)]> {
6375  bits<5> Rd;
6376  bits<5> Rn;
6377  let Inst{31}    = 0;
6378  let Inst{30}    = Q;
6379  let Inst{29}    = U;
6380  let Inst{28-24} = 0b01110;
6381  let Inst{23-22} = size;
6382  let Inst{21} = 0b1;
6383  let Inst{20-19} = size2;
6384  let Inst{18-17} = 0b00;
6385  let Inst{16-12} = opcode;
6386  let Inst{11-10} = 0b10;
6387  let Inst{9-5}   = Rn;
6388  let Inst{4-0}   = Rd;
6389}
6390
6391// Comparisons support all element sizes, except 1xD.
6392multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6393                            SDNode OpNode> {
6394  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6395                                     asm, ".8b", "0",
6396                                     v8i8, v8i8, OpNode>;
6397  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6398                                     asm, ".16b", "0",
6399                                     v16i8, v16i8, OpNode>;
6400  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6401                                     asm, ".4h", "0",
6402                                     v4i16, v4i16, OpNode>;
6403  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6404                                     asm, ".8h", "0",
6405                                     v8i16, v8i16, OpNode>;
6406  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6407                                     asm, ".2s", "0",
6408                                     v2i32, v2i32, OpNode>;
6409  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6410                                     asm, ".4s", "0",
6411                                     v4i32, v4i32, OpNode>;
6412  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6413                                     asm, ".2d", "0",
6414                                     v2i64, v2i64, OpNode>;
6415}
6416
6417// FP Comparisons support only S and D element sizes (and H for v8.2a).
6418multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6419                              string asm, SDNode OpNode> {
6420
6421  let mayRaiseFPException = 1, Uses = [FPCR] in {
6422  let Predicates = [HasNEON, HasFullFP16] in {
6423  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6424                                     asm, ".4h", "0.0",
6425                                     v4i16, v4f16, OpNode>;
6426  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6427                                     asm, ".8h", "0.0",
6428                                     v8i16, v8f16, OpNode>;
6429  } // Predicates = [HasNEON, HasFullFP16]
6430  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6431                                     asm, ".2s", "0.0",
6432                                     v2i32, v2f32, OpNode>;
6433  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6434                                     asm, ".4s", "0.0",
6435                                     v4i32, v4f32, OpNode>;
6436  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6437                                     asm, ".2d", "0.0",
6438                                     v2i64, v2f64, OpNode>;
6439  }
6440
6441  let Predicates = [HasNEON, HasFullFP16] in {
6442  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6443                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6444  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6445                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6446  }
6447  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6448                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6449  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6450                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6451  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6452                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6453  let Predicates = [HasNEON, HasFullFP16] in {
6454  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6455                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6456  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6457                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6458  }
6459  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6460                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6461  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6462                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6463  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6464                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6465}
6466
6467let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6468class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6469                             RegisterOperand outtype, RegisterOperand intype,
6470                             string asm, string VdTy, string VnTy,
6471                             list<dag> pattern>
6472  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6473      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6474    Sched<[WriteVq]> {
6475  bits<5> Rd;
6476  bits<5> Rn;
6477  let Inst{31}    = 0;
6478  let Inst{30}    = Q;
6479  let Inst{29}    = U;
6480  let Inst{28-24} = 0b01110;
6481  let Inst{23-22} = size;
6482  let Inst{21-17} = 0b10000;
6483  let Inst{16-12} = opcode;
6484  let Inst{11-10} = 0b10;
6485  let Inst{9-5}   = Rn;
6486  let Inst{4-0}   = Rd;
6487}
6488
6489let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6490class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6491                             RegisterOperand outtype, RegisterOperand intype,
6492                             string asm, string VdTy, string VnTy,
6493                             list<dag> pattern>
6494  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6495      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6496    Sched<[WriteVq]> {
6497  bits<5> Rd;
6498  bits<5> Rn;
6499  let Inst{31}    = 0;
6500  let Inst{30}    = Q;
6501  let Inst{29}    = U;
6502  let Inst{28-24} = 0b01110;
6503  let Inst{23-22} = size;
6504  let Inst{21-17} = 0b10000;
6505  let Inst{16-12} = opcode;
6506  let Inst{11-10} = 0b10;
6507  let Inst{9-5}   = Rn;
6508  let Inst{4-0}   = Rd;
6509}
6510
6511multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6512  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6513                                    asm, ".4s", ".4h", []>;
6514  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6515                                    asm#"2", ".4s", ".8h", []>;
6516  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6517                                    asm, ".2d", ".2s", []>;
6518  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6519                                    asm#"2", ".2d", ".4s", []>;
6520}
6521
6522multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6523  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6524                                    asm, ".4h", ".4s", []>;
6525  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6526                                    asm#"2", ".8h", ".4s", []>;
6527  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6528                                    asm, ".2s", ".2d", []>;
6529  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6530                                    asm#"2", ".4s", ".2d", []>;
6531}
6532
6533multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6534                                     Intrinsic OpNode> {
6535  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6536                                     asm, ".2s", ".2d",
6537                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6538  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6539                                    asm#"2", ".4s", ".2d", []>;
6540
6541  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6542            (!cast<Instruction>(NAME # "v4f32")
6543                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6544}
6545
6546//----------------------------------------------------------------------------
6547// AdvSIMD three register different-size vector instructions.
6548//----------------------------------------------------------------------------
6549
6550let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6551class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6552                      RegisterOperand outtype, RegisterOperand intype1,
6553                      RegisterOperand intype2, string asm,
6554                      string outkind, string inkind1, string inkind2,
6555                      list<dag> pattern>
6556  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6557      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6558      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6559    Sched<[WriteVq]> {
6560  bits<5> Rd;
6561  bits<5> Rn;
6562  bits<5> Rm;
6563  let Inst{31}    = 0;
6564  let Inst{30}    = size{0};
6565  let Inst{29}    = U;
6566  let Inst{28-24} = 0b01110;
6567  let Inst{23-22} = size{2-1};
6568  let Inst{21}    = 1;
6569  let Inst{20-16} = Rm;
6570  let Inst{15-12} = opcode;
6571  let Inst{11-10} = 0b00;
6572  let Inst{9-5}   = Rn;
6573  let Inst{4-0}   = Rd;
6574}
6575
6576let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6577class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6578                      RegisterOperand outtype, RegisterOperand intype1,
6579                      RegisterOperand intype2, string asm,
6580                      string outkind, string inkind1, string inkind2,
6581                      list<dag> pattern>
6582  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6583      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6584      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6585    Sched<[WriteVq]> {
6586  bits<5> Rd;
6587  bits<5> Rn;
6588  bits<5> Rm;
6589  let Inst{31}    = 0;
6590  let Inst{30}    = size{0};
6591  let Inst{29}    = U;
6592  let Inst{28-24} = 0b01110;
6593  let Inst{23-22} = size{2-1};
6594  let Inst{21}    = 1;
6595  let Inst{20-16} = Rm;
6596  let Inst{15-12} = opcode;
6597  let Inst{11-10} = 0b00;
6598  let Inst{9-5}   = Rn;
6599  let Inst{4-0}   = Rd;
6600}
6601
6602// FIXME: TableGen doesn't know how to deal with expanded types that also
6603//        change the element count (in this case, placing the results in
6604//        the high elements of the result register rather than the low
6605//        elements). Until that's fixed, we can't code-gen those.
6606multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6607                                    Intrinsic IntOp> {
6608  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6609                                                  V64, V128, V128,
6610                                                  asm, ".8b", ".8h", ".8h",
6611     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6612  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6613                                                  V128, V128, V128,
6614                                                  asm#"2", ".16b", ".8h", ".8h",
6615     []>;
6616  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6617                                                  V64, V128, V128,
6618                                                  asm, ".4h", ".4s", ".4s",
6619     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6620  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6621                                                  V128, V128, V128,
6622                                                  asm#"2", ".8h", ".4s", ".4s",
6623     []>;
6624  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6625                                                  V64, V128, V128,
6626                                                  asm, ".2s", ".2d", ".2d",
6627     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6628  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6629                                                  V128, V128, V128,
6630                                                  asm#"2", ".4s", ".2d", ".2d",
6631     []>;
6632
6633
6634  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6635  // a version attached to an instruction.
6636  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6637                                                   (v8i16 V128:$Rm))),
6638            (!cast<Instruction>(NAME # "v8i16_v16i8")
6639                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6640                V128:$Rn, V128:$Rm)>;
6641  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6642                                                    (v4i32 V128:$Rm))),
6643            (!cast<Instruction>(NAME # "v4i32_v8i16")
6644                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6645                V128:$Rn, V128:$Rm)>;
6646  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6647                                                    (v2i64 V128:$Rm))),
6648            (!cast<Instruction>(NAME # "v2i64_v4i32")
6649                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6650                V128:$Rn, V128:$Rm)>;
6651}
6652
6653multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6654                                      SDPatternOperator OpNode> {
6655  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6656                                            V128, V64, V64,
6657                                            asm, ".8h", ".8b", ".8b",
6658      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6659  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6660                                            V128, V128, V128,
6661                                            asm#"2", ".8h", ".16b", ".16b", []>;
6662  let Predicates = [HasAES] in {
6663    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6664                                              V128, V64, V64,
6665                                              asm, ".1q", ".1d", ".1d",
6666        [(set (v16i8 V128:$Rd), (OpNode (v1i64 V64:$Rn), (v1i64 V64:$Rm)))]>;
6667    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6668                                              V128, V128, V128,
6669                                              asm#"2", ".1q", ".2d", ".2d",
6670        [(set (v16i8 V128:$Rd), (OpNode (extract_high_v2i64 (v2i64 V128:$Rn)),
6671                                        (extract_high_v2i64 (v2i64 V128:$Rm))))]>;
6672  }
6673
6674  def : Pat<(v8i16 (OpNode (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6675                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6676      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6677}
6678
6679multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6680                                 SDPatternOperator OpNode> {
6681  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6682                                                  V128, V64, V64,
6683                                                  asm, ".4s", ".4h", ".4h",
6684      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6685  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6686                                                  V128, V128, V128,
6687                                                  asm#"2", ".4s", ".8h", ".8h",
6688      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6689                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6690  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6691                                                  V128, V64, V64,
6692                                                  asm, ".2d", ".2s", ".2s",
6693      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6694  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6695                                                  V128, V128, V128,
6696                                                  asm#"2", ".2d", ".4s", ".4s",
6697      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6698                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6699}
6700
6701multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6702                                  SDPatternOperator OpNode = null_frag> {
6703  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6704                                                  V128, V64, V64,
6705                                                  asm, ".8h", ".8b", ".8b",
6706      [(set (v8i16 V128:$Rd),
6707            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6708  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6709                                                 V128, V128, V128,
6710                                                 asm#"2", ".8h", ".16b", ".16b",
6711      [(set (v8i16 V128:$Rd),
6712            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6713                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
6714  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6715                                                  V128, V64, V64,
6716                                                  asm, ".4s", ".4h", ".4h",
6717      [(set (v4i32 V128:$Rd),
6718            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6719  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6720                                                  V128, V128, V128,
6721                                                  asm#"2", ".4s", ".8h", ".8h",
6722      [(set (v4i32 V128:$Rd),
6723            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6724                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6725  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6726                                                  V128, V64, V64,
6727                                                  asm, ".2d", ".2s", ".2s",
6728      [(set (v2i64 V128:$Rd),
6729            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6730  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6731                                                  V128, V128, V128,
6732                                                  asm#"2", ".2d", ".4s", ".4s",
6733      [(set (v2i64 V128:$Rd),
6734            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6735                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6736}
6737
6738multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6739                                          string asm,
6740                                          SDPatternOperator OpNode> {
6741  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6742                                                  V128, V64, V64,
6743                                                  asm, ".8h", ".8b", ".8b",
6744    [(set (v8i16 V128:$dst),
6745          (add (v8i16 V128:$Rd),
6746               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6747  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6748                                                 V128, V128, V128,
6749                                                 asm#"2", ".8h", ".16b", ".16b",
6750    [(set (v8i16 V128:$dst),
6751          (add (v8i16 V128:$Rd),
6752               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6753                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
6754  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6755                                                  V128, V64, V64,
6756                                                  asm, ".4s", ".4h", ".4h",
6757    [(set (v4i32 V128:$dst),
6758          (add (v4i32 V128:$Rd),
6759               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6760  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6761                                                  V128, V128, V128,
6762                                                  asm#"2", ".4s", ".8h", ".8h",
6763    [(set (v4i32 V128:$dst),
6764          (add (v4i32 V128:$Rd),
6765               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6766                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
6767  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6768                                                  V128, V64, V64,
6769                                                  asm, ".2d", ".2s", ".2s",
6770    [(set (v2i64 V128:$dst),
6771          (add (v2i64 V128:$Rd),
6772               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6773  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6774                                                  V128, V128, V128,
6775                                                  asm#"2", ".2d", ".4s", ".4s",
6776    [(set (v2i64 V128:$dst),
6777          (add (v2i64 V128:$Rd),
6778               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6779                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
6780}
6781
6782multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6783                                  SDPatternOperator OpNode = null_frag> {
6784  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6785                                                  V128, V64, V64,
6786                                                  asm, ".8h", ".8b", ".8b",
6787      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6788  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6789                                                 V128, V128, V128,
6790                                                 asm#"2", ".8h", ".16b", ".16b",
6791      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6792                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6793  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6794                                                  V128, V64, V64,
6795                                                  asm, ".4s", ".4h", ".4h",
6796      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6797  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6798                                                  V128, V128, V128,
6799                                                  asm#"2", ".4s", ".8h", ".8h",
6800      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6801                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6802  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6803                                                  V128, V64, V64,
6804                                                  asm, ".2d", ".2s", ".2s",
6805      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6806  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6807                                                  V128, V128, V128,
6808                                                  asm#"2", ".2d", ".4s", ".4s",
6809      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6810                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6811}
6812
6813multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6814                                      string asm,
6815                                      SDPatternOperator OpNode> {
6816  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6817                                                  V128, V64, V64,
6818                                                  asm, ".8h", ".8b", ".8b",
6819    [(set (v8i16 V128:$dst),
6820          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6821  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6822                                                 V128, V128, V128,
6823                                                 asm#"2", ".8h", ".16b", ".16b",
6824    [(set (v8i16 V128:$dst),
6825          (OpNode (v8i16 V128:$Rd),
6826                  (extract_high_v16i8 (v16i8 V128:$Rn)),
6827                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6828  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6829                                                  V128, V64, V64,
6830                                                  asm, ".4s", ".4h", ".4h",
6831    [(set (v4i32 V128:$dst),
6832          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6833  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6834                                                  V128, V128, V128,
6835                                                  asm#"2", ".4s", ".8h", ".8h",
6836    [(set (v4i32 V128:$dst),
6837          (OpNode (v4i32 V128:$Rd),
6838                  (extract_high_v8i16 (v8i16 V128:$Rn)),
6839                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6840  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6841                                                  V128, V64, V64,
6842                                                  asm, ".2d", ".2s", ".2s",
6843    [(set (v2i64 V128:$dst),
6844          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6845  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6846                                                  V128, V128, V128,
6847                                                  asm#"2", ".2d", ".4s", ".4s",
6848    [(set (v2i64 V128:$dst),
6849          (OpNode (v2i64 V128:$Rd),
6850                  (extract_high_v4i32 (v4i32 V128:$Rn)),
6851                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6852}
6853
6854multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6855                                           SDPatternOperator Accum> {
6856  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6857                                                  V128, V64, V64,
6858                                                  asm, ".4s", ".4h", ".4h",
6859    [(set (v4i32 V128:$dst),
6860          (Accum (v4i32 V128:$Rd),
6861                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6862                                                (v4i16 V64:$Rm)))))]>;
6863  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6864                                                  V128, V128, V128,
6865                                                  asm#"2", ".4s", ".8h", ".8h",
6866    [(set (v4i32 V128:$dst),
6867          (Accum (v4i32 V128:$Rd),
6868                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
6869                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6870  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6871                                                  V128, V64, V64,
6872                                                  asm, ".2d", ".2s", ".2s",
6873    [(set (v2i64 V128:$dst),
6874          (Accum (v2i64 V128:$Rd),
6875                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6876                                                (v2i32 V64:$Rm)))))]>;
6877  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6878                                                  V128, V128, V128,
6879                                                  asm#"2", ".2d", ".4s", ".4s",
6880    [(set (v2i64 V128:$dst),
6881          (Accum (v2i64 V128:$Rd),
6882                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
6883                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6884}
6885
6886multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6887                                  SDPatternOperator OpNode> {
6888  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6889                                                  V128, V128, V64,
6890                                                  asm, ".8h", ".8h", ".8b",
6891       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6892  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6893                                                  V128, V128, V128,
6894                                                  asm#"2", ".8h", ".8h", ".16b",
6895       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6896                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6897  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6898                                                  V128, V128, V64,
6899                                                  asm, ".4s", ".4s", ".4h",
6900       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6901  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6902                                                  V128, V128, V128,
6903                                                  asm#"2", ".4s", ".4s", ".8h",
6904       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6905                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6906  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6907                                                  V128, V128, V64,
6908                                                  asm, ".2d", ".2d", ".2s",
6909       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6910  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6911                                                  V128, V128, V128,
6912                                                  asm#"2", ".2d", ".2d", ".4s",
6913       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6914                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6915}
6916
6917//----------------------------------------------------------------------------
6918// AdvSIMD bitwise extract from vector
6919//----------------------------------------------------------------------------
6920
6921class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6922                             string asm, string kind>
6923  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6924      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6925      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6926      [(set (vty regtype:$Rd),
6927            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6928    Sched<[!if(size, WriteVq, WriteVd)]> {
6929  bits<5> Rd;
6930  bits<5> Rn;
6931  bits<5> Rm;
6932  bits<4> imm;
6933  let Inst{31}    = 0;
6934  let Inst{30}    = size;
6935  let Inst{29-21} = 0b101110000;
6936  let Inst{20-16} = Rm;
6937  let Inst{15}    = 0;
6938  let Inst{14-11} = imm;
6939  let Inst{10}    = 0;
6940  let Inst{9-5}   = Rn;
6941  let Inst{4-0}   = Rd;
6942}
6943
6944
6945multiclass SIMDBitwiseExtract<string asm> {
6946  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6947    let imm{3} = 0;
6948  }
6949  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6950}
6951
6952//----------------------------------------------------------------------------
6953// AdvSIMD zip vector
6954//----------------------------------------------------------------------------
6955
6956class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6957                        string asm, string kind, SDNode OpNode, ValueType valty>
6958  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6959      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6960      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6961      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6962    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
6963  bits<5> Rd;
6964  bits<5> Rn;
6965  bits<5> Rm;
6966  let Inst{31}    = 0;
6967  let Inst{30}    = size{0};
6968  let Inst{29-24} = 0b001110;
6969  let Inst{23-22} = size{2-1};
6970  let Inst{21}    = 0;
6971  let Inst{20-16} = Rm;
6972  let Inst{15}    = 0;
6973  let Inst{14-12} = opc;
6974  let Inst{11-10} = 0b10;
6975  let Inst{9-5}   = Rn;
6976  let Inst{4-0}   = Rd;
6977}
6978
6979multiclass SIMDZipVector<bits<3>opc, string asm,
6980                         SDNode OpNode> {
6981  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6982      asm, ".8b", OpNode, v8i8>;
6983  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6984      asm, ".16b", OpNode, v16i8>;
6985  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6986      asm, ".4h", OpNode, v4i16>;
6987  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6988      asm, ".8h", OpNode, v8i16>;
6989  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6990      asm, ".2s", OpNode, v2i32>;
6991  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6992      asm, ".4s", OpNode, v4i32>;
6993  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6994      asm, ".2d", OpNode, v2i64>;
6995
6996  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6997        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6998  def : Pat<(v4bf16 (OpNode V64:$Rn, V64:$Rm)),
6999        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7000  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
7001        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7002  def : Pat<(v8bf16 (OpNode V128:$Rn, V128:$Rm)),
7003        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7004  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
7005        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
7006  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
7007        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
7008  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
7009        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
7010}
7011
7012//----------------------------------------------------------------------------
7013// AdvSIMD three register scalar instructions
7014//----------------------------------------------------------------------------
7015
7016let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7017class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
7018                        RegisterClass regtype, string asm,
7019                        list<dag> pattern>
7020  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7021      "\t$Rd, $Rn, $Rm", "", pattern>,
7022    Sched<[WriteVd]> {
7023  bits<5> Rd;
7024  bits<5> Rn;
7025  bits<5> Rm;
7026  let Inst{31-30} = 0b01;
7027  let Inst{29}    = U;
7028  let Inst{28-24} = 0b11110;
7029  let Inst{23-21} = size;
7030  let Inst{20-16} = Rm;
7031  let Inst{15-11} = opcode;
7032  let Inst{10}    = 1;
7033  let Inst{9-5}   = Rn;
7034  let Inst{4-0}   = Rd;
7035}
7036
7037let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7038class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
7039                        dag oops, dag iops, string asm,
7040            list<dag> pattern>
7041  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
7042    Sched<[WriteVd]> {
7043  bits<5> Rd;
7044  bits<5> Rn;
7045  bits<5> Rm;
7046  let Inst{31-30} = 0b01;
7047  let Inst{29}    = U;
7048  let Inst{28-24} = 0b11110;
7049  let Inst{23-22} = size;
7050  let Inst{21}    = R;
7051  let Inst{20-16} = Rm;
7052  let Inst{15-11} = opcode;
7053  let Inst{10}    = 1;
7054  let Inst{9-5}   = Rn;
7055  let Inst{4-0}   = Rd;
7056}
7057
7058multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
7059                            SDPatternOperator OpNode> {
7060  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7061    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7062}
7063
7064multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
7065                               SDPatternOperator OpNode> {
7066  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7067    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7068  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
7069  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7070  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
7071
7072  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7073            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
7074  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
7075            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
7076}
7077
7078multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
7079                             SDPatternOperator OpNode> {
7080  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
7081                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7082  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7083}
7084
7085multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
7086  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
7087                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
7088                                     asm, []>;
7089  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
7090                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
7091                                     asm, []>;
7092}
7093
7094multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
7095                             SDPatternOperator OpNode = null_frag,
7096                             Predicate pred = HasNEON> {
7097  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7098    let Predicates = [pred] in {
7099    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7100      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7101    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7102      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7103    }
7104    let Predicates = [pred, HasFullFP16] in {
7105    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7106      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
7107    }
7108  }
7109
7110  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7111            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7112}
7113
7114multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
7115                                SDPatternOperator OpNode = null_frag> {
7116  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7117    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7118      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7119    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7120      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
7121    let Predicates = [HasNEON, HasFullFP16] in {
7122    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7123      []>;
7124    } // Predicates = [HasNEON, HasFullFP16]
7125  }
7126
7127  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7128            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7129}
7130
7131class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
7132              dag oops, dag iops, string asm, string cstr, list<dag> pat>
7133  : I<oops, iops, asm,
7134      "\t$Rd, $Rn, $Rm", cstr, pat>,
7135    Sched<[WriteVd]> {
7136  bits<5> Rd;
7137  bits<5> Rn;
7138  bits<5> Rm;
7139  let Inst{31-30} = 0b01;
7140  let Inst{29}    = U;
7141  let Inst{28-24} = 0b11110;
7142  let Inst{23-22} = size;
7143  let Inst{21}    = 1;
7144  let Inst{20-16} = Rm;
7145  let Inst{15-11} = opcode;
7146  let Inst{10}    = 0;
7147  let Inst{9-5}   = Rn;
7148  let Inst{4-0}   = Rd;
7149}
7150
7151let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7152multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
7153                                  SDPatternOperator OpNode = null_frag> {
7154  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7155                                      (outs FPR32:$Rd),
7156                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7157  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7158                                      (outs FPR64:$Rd),
7159                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7160            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7161}
7162
7163let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7164multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7165                                  SDPatternOperator OpNode = null_frag> {
7166  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7167                                      (outs FPR32:$dst),
7168                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7169                                      asm, "$Rd = $dst", []>;
7170  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7171                                      (outs FPR64:$dst),
7172                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7173                                      asm, "$Rd = $dst",
7174            [(set (i64 FPR64:$dst),
7175                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7176}
7177
7178//----------------------------------------------------------------------------
7179// AdvSIMD two register scalar instructions
7180//----------------------------------------------------------------------------
7181
7182let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7183class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7184                        RegisterClass regtype, RegisterClass regtype2,
7185                        string asm, list<dag> pat>
7186  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7187      "\t$Rd, $Rn", "", pat>,
7188    Sched<[WriteVd]> {
7189  bits<5> Rd;
7190  bits<5> Rn;
7191  let Inst{31-30} = 0b01;
7192  let Inst{29}    = U;
7193  let Inst{28-24} = 0b11110;
7194  let Inst{23-22} = size;
7195  let Inst{21} = 0b1;
7196  let Inst{20-19} = size2;
7197  let Inst{18-17} = 0b00;
7198  let Inst{16-12} = opcode;
7199  let Inst{11-10} = 0b10;
7200  let Inst{9-5}   = Rn;
7201  let Inst{4-0}   = Rd;
7202}
7203
7204let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7205class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7206                        RegisterClass regtype, RegisterClass regtype2,
7207                        string asm, list<dag> pat>
7208  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7209      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7210    Sched<[WriteVd]> {
7211  bits<5> Rd;
7212  bits<5> Rn;
7213  let Inst{31-30} = 0b01;
7214  let Inst{29}    = U;
7215  let Inst{28-24} = 0b11110;
7216  let Inst{23-22} = size;
7217  let Inst{21-17} = 0b10000;
7218  let Inst{16-12} = opcode;
7219  let Inst{11-10} = 0b10;
7220  let Inst{9-5}   = Rn;
7221  let Inst{4-0}   = Rd;
7222}
7223
7224
7225let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7226class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7227                        RegisterClass regtype, string asm, string zero>
7228  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7229      "\t$Rd, $Rn, #" # zero, "", []>,
7230    Sched<[WriteVd]> {
7231  bits<5> Rd;
7232  bits<5> Rn;
7233  let Inst{31-30} = 0b01;
7234  let Inst{29}    = U;
7235  let Inst{28-24} = 0b11110;
7236  let Inst{23-22} = size;
7237  let Inst{21} = 0b1;
7238  let Inst{20-19} = size2;
7239  let Inst{18-17} = 0b00;
7240  let Inst{16-12} = opcode;
7241  let Inst{11-10} = 0b10;
7242  let Inst{9-5}   = Rn;
7243  let Inst{4-0}   = Rd;
7244}
7245
7246let mayRaiseFPException = 1, Uses = [FPCR] in
7247class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7248  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7249     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7250    Sched<[WriteVd]> {
7251  bits<5> Rd;
7252  bits<5> Rn;
7253  let Inst{31-17} = 0b011111100110000;
7254  let Inst{16-12} = opcode;
7255  let Inst{11-10} = 0b10;
7256  let Inst{9-5}   = Rn;
7257  let Inst{4-0}   = Rd;
7258}
7259
7260multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7261                             SDPatternOperator OpNode> {
7262  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7263
7264  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7265            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7266}
7267
7268multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7269                              SDPatternOperator OpNode> {
7270  let mayRaiseFPException = 1, Uses = [FPCR] in {
7271  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7272  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7273  let Predicates = [HasNEON, HasFullFP16] in {
7274  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7275  }
7276  }
7277
7278  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7279                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7280  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7281                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7282  let Predicates = [HasNEON, HasFullFP16] in {
7283  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7284                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7285  }
7286
7287  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7288            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7289}
7290
7291multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7292                          SDPatternOperator OpNode = null_frag,
7293                          list<Predicate> preds = []> {
7294  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7295    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7296
7297  let Predicates = preds in {
7298  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7299            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7300  }
7301}
7302
7303let mayRaiseFPException = 1, Uses = [FPCR] in
7304multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7305                           Predicate pred = HasNEON> {
7306  let Predicates = [pred] in {
7307  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7308  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7309  }
7310  let Predicates = [pred, HasFullFP16] in {
7311  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7312  }
7313}
7314
7315let mayRaiseFPException = 1, Uses = [FPCR] in
7316multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7317                              SDPatternOperator OpNode> {
7318  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7319                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7320  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7321                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7322  let Predicates = [HasNEON, HasFullFP16] in {
7323  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7324                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7325  }
7326}
7327
7328multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7329                             SDPatternOperator OpNode = null_frag> {
7330  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7331    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7332           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7333    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7334           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7335    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7336    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7337  }
7338
7339  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7340            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7341}
7342
7343multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7344                                 Intrinsic OpNode> {
7345  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7346    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7347        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7348    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7349        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7350    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7351    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7352  }
7353
7354  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7355            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7356}
7357
7358
7359
7360let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7361multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7362                                 SDPatternOperator OpNode = null_frag> {
7363  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7364        [(set (f32 FPR32:$Rd), (OpNode (f64 FPR64:$Rn)))]>;
7365  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7366  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7367}
7368
7369//----------------------------------------------------------------------------
7370// AdvSIMD scalar pairwise instructions
7371//----------------------------------------------------------------------------
7372
7373let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7374class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7375                        RegisterOperand regtype, RegisterOperand vectype,
7376                        string asm, string kind>
7377  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7378      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7379    Sched<[WriteVd]> {
7380  bits<5> Rd;
7381  bits<5> Rn;
7382  let Inst{31-30} = 0b01;
7383  let Inst{29}    = U;
7384  let Inst{28-24} = 0b11110;
7385  let Inst{23-22} = size;
7386  let Inst{21-17} = 0b11000;
7387  let Inst{16-12} = opcode;
7388  let Inst{11-10} = 0b10;
7389  let Inst{9-5}   = Rn;
7390  let Inst{4-0}   = Rd;
7391}
7392
7393multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7394  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7395                                      asm, ".2d">;
7396}
7397
7398let mayRaiseFPException = 1, Uses = [FPCR] in
7399multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7400  let Predicates = [HasNEON, HasFullFP16] in {
7401  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7402                                      asm, ".2h">;
7403  }
7404  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7405                                      asm, ".2s">;
7406  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7407                                      asm, ".2d">;
7408}
7409
7410//----------------------------------------------------------------------------
7411// AdvSIMD across lanes instructions
7412//----------------------------------------------------------------------------
7413
7414let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7415class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7416                          RegisterClass regtype, RegisterOperand vectype,
7417                          string asm, string kind, list<dag> pattern>
7418  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7419      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7420    Sched<[!if(Q, WriteVq, WriteVd)]> {
7421  bits<5> Rd;
7422  bits<5> Rn;
7423  let Inst{31}    = 0;
7424  let Inst{30}    = Q;
7425  let Inst{29}    = U;
7426  let Inst{28-24} = 0b01110;
7427  let Inst{23-22} = size;
7428  let Inst{21-17} = 0b11000;
7429  let Inst{16-12} = opcode;
7430  let Inst{11-10} = 0b10;
7431  let Inst{9-5}   = Rn;
7432  let Inst{4-0}   = Rd;
7433}
7434
7435multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7436                              string asm> {
7437  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7438                                   asm, ".8b", []>;
7439  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7440                                   asm, ".16b", []>;
7441  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7442                                   asm, ".4h", []>;
7443  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7444                                   asm, ".8h", []>;
7445  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7446                                   asm, ".4s", []>;
7447}
7448
7449multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7450  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7451                                   asm, ".8b", []>;
7452  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7453                                   asm, ".16b", []>;
7454  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7455                                   asm, ".4h", []>;
7456  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7457                                   asm, ".8h", []>;
7458  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7459                                   asm, ".4s", []>;
7460}
7461
7462let mayRaiseFPException = 1, Uses = [FPCR] in
7463multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7464                            Intrinsic intOp> {
7465  let Predicates = [HasNEON, HasFullFP16] in {
7466  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7467                                   asm, ".4h",
7468        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7469  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7470                                   asm, ".8h",
7471        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7472  } // Predicates = [HasNEON, HasFullFP16]
7473  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7474                                   asm, ".4s",
7475        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7476}
7477
7478//----------------------------------------------------------------------------
7479// AdvSIMD INS/DUP instructions
7480//----------------------------------------------------------------------------
7481
7482// FIXME: There has got to be a better way to factor these. ugh.
7483
7484class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7485                     string operands, string constraints, list<dag> pattern>
7486  : I<outs, ins, asm, operands, constraints, pattern>,
7487    Sched<[!if(Q, WriteVq, WriteVd)]> {
7488  bits<5> Rd;
7489  bits<5> Rn;
7490  let Inst{31} = 0;
7491  let Inst{30} = Q;
7492  let Inst{29} = op;
7493  let Inst{28-21} = 0b01110000;
7494  let Inst{15} = 0;
7495  let Inst{10} = 1;
7496  let Inst{9-5} = Rn;
7497  let Inst{4-0} = Rd;
7498}
7499
7500class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7501                      RegisterOperand vecreg, RegisterClass regtype>
7502  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7503                   "{\t$Rd" # size # ", $Rn" #
7504                   "|" # size # "\t$Rd, $Rn}", "",
7505                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7506  let Inst{20-16} = imm5;
7507  let Inst{14-11} = 0b0001;
7508}
7509
7510class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7511                         ValueType vectype, ValueType insreg,
7512                         RegisterOperand vecreg, Operand idxtype,
7513                         SDNode OpNode>
7514  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7515                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7516                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7517                 [(set (vectype vecreg:$Rd),
7518                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7519  let Inst{14-11} = 0b0000;
7520}
7521
7522class SIMDDup64FromElement
7523  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7524                       VectorIndexD, AArch64duplane64> {
7525  bits<1> idx;
7526  let Inst{20} = idx;
7527  let Inst{19-16} = 0b1000;
7528}
7529
7530class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7531                           RegisterOperand vecreg>
7532  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7533                       VectorIndexS, AArch64duplane32> {
7534  bits<2> idx;
7535  let Inst{20-19} = idx;
7536  let Inst{18-16} = 0b100;
7537}
7538
7539class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7540                           RegisterOperand vecreg>
7541  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7542                       VectorIndexH, AArch64duplane16> {
7543  bits<3> idx;
7544  let Inst{20-18} = idx;
7545  let Inst{17-16} = 0b10;
7546}
7547
7548class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7549                          RegisterOperand vecreg>
7550  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7551                       VectorIndexB, AArch64duplane8> {
7552  bits<4> idx;
7553  let Inst{20-17} = idx;
7554  let Inst{16} = 1;
7555}
7556
7557class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7558                  Operand idxtype, string asm, list<dag> pattern>
7559  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7560                   "{\t$Rd, $Rn" # size # "$idx" #
7561                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7562  let Inst{14-11} = imm4;
7563}
7564
7565class SIMDSMov<bit Q, string size, RegisterClass regtype,
7566               Operand idxtype>
7567  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7568class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7569               Operand idxtype>
7570  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7571      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7572
7573class SIMDMovAlias<string asm, string size, Instruction inst,
7574                   RegisterClass regtype, Operand idxtype>
7575    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7576                    "|" # size # "\t$dst, $src$idx}",
7577                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7578
7579multiclass SMov {
7580  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7581  // streaming mode.
7582  let Predicates = [HasNEONorSME] in {
7583    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7584      let Inst{20-16} = 0b00001;
7585    }
7586    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7587      let Inst{20-16} = 0b00001;
7588    }
7589    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7590      let Inst{20-16} = 0b00010;
7591    }
7592    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7593      let Inst{20-16} = 0b00010;
7594    }
7595    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7596      let Inst{20-16} = 0b00100;
7597    }
7598  }
7599  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7600    bits<4> idx;
7601    let Inst{20-17} = idx;
7602    let Inst{16} = 1;
7603  }
7604  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7605    bits<4> idx;
7606    let Inst{20-17} = idx;
7607    let Inst{16} = 1;
7608  }
7609  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7610    bits<3> idx;
7611    let Inst{20-18} = idx;
7612    let Inst{17-16} = 0b10;
7613  }
7614  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7615    bits<3> idx;
7616    let Inst{20-18} = idx;
7617    let Inst{17-16} = 0b10;
7618  }
7619  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7620    bits<2> idx;
7621    let Inst{20-19} = idx;
7622    let Inst{18-16} = 0b100;
7623  }
7624}
7625
7626multiclass UMov {
7627  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7628  // streaming mode.
7629  let Predicates = [HasNEONorSME] in {
7630    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7631      let Inst{20-16} = 0b00001;
7632    }
7633    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7634      let Inst{20-16} = 0b00010;
7635    }
7636    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7637      let Inst{20-16} = 0b00100;
7638    }
7639    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7640      let Inst{20-16} = 0b01000;
7641    }
7642    def : SIMDMovAlias<"mov", ".s",
7643                       !cast<Instruction>(NAME # vi32_idx0),
7644                       GPR32, VectorIndex0>;
7645    def : SIMDMovAlias<"mov", ".d",
7646                       !cast<Instruction>(NAME # vi64_idx0),
7647                       GPR64, VectorIndex0>;
7648  }
7649  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7650    bits<4> idx;
7651    let Inst{20-17} = idx;
7652    let Inst{16} = 1;
7653  }
7654  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7655    bits<3> idx;
7656    let Inst{20-18} = idx;
7657    let Inst{17-16} = 0b10;
7658  }
7659  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7660    bits<2> idx;
7661    let Inst{20-19} = idx;
7662    let Inst{18-16} = 0b100;
7663  }
7664  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7665    bits<1> idx;
7666    let Inst{20} = idx;
7667    let Inst{19-16} = 0b1000;
7668  }
7669  def : SIMDMovAlias<"mov", ".s",
7670                     !cast<Instruction>(NAME#"vi32"),
7671                     GPR32, VectorIndexS>;
7672  def : SIMDMovAlias<"mov", ".d",
7673                     !cast<Instruction>(NAME#"vi64"),
7674                     GPR64, VectorIndexD>;
7675}
7676
7677class SIMDInsFromMain<string size, ValueType vectype,
7678                      RegisterClass regtype, Operand idxtype>
7679  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7680                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7681                   "{\t$Rd" # size # "$idx, $Rn" #
7682                   "|" # size # "\t$Rd$idx, $Rn}",
7683                   "$Rd = $dst",
7684            [(set V128:$dst,
7685              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7686  let Inst{14-11} = 0b0011;
7687}
7688
7689class SIMDInsFromElement<string size, ValueType vectype,
7690                         ValueType elttype, Operand idxtype>
7691  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7692                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7693                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7694                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7695                   "$Rd = $dst",
7696         [(set V128:$dst,
7697               (vector_insert
7698                 (vectype V128:$Rd),
7699                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7700                 idxtype:$idx))]>;
7701
7702class SIMDInsMainMovAlias<string size, Instruction inst,
7703                          RegisterClass regtype, Operand idxtype>
7704    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7705                        "|" # size #"\t$dst$idx, $src}",
7706                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7707class SIMDInsElementMovAlias<string size, Instruction inst,
7708                             Operand idxtype>
7709    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7710                      # "|" # size #"\t$dst$idx, $src$idx2}",
7711                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7712
7713
7714multiclass SIMDIns {
7715  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7716    bits<4> idx;
7717    let Inst{20-17} = idx;
7718    let Inst{16} = 1;
7719  }
7720  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7721    bits<3> idx;
7722    let Inst{20-18} = idx;
7723    let Inst{17-16} = 0b10;
7724  }
7725  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7726    bits<2> idx;
7727    let Inst{20-19} = idx;
7728    let Inst{18-16} = 0b100;
7729  }
7730  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7731    bits<1> idx;
7732    let Inst{20} = idx;
7733    let Inst{19-16} = 0b1000;
7734  }
7735
7736  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7737    bits<4> idx;
7738    bits<4> idx2;
7739    let Inst{20-17} = idx;
7740    let Inst{16} = 1;
7741    let Inst{14-11} = idx2;
7742  }
7743  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7744    bits<3> idx;
7745    bits<3> idx2;
7746    let Inst{20-18} = idx;
7747    let Inst{17-16} = 0b10;
7748    let Inst{14-12} = idx2;
7749    let Inst{11} = {?};
7750  }
7751  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7752    bits<2> idx;
7753    bits<2> idx2;
7754    let Inst{20-19} = idx;
7755    let Inst{18-16} = 0b100;
7756    let Inst{14-13} = idx2;
7757    let Inst{12-11} = {?,?};
7758  }
7759  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7760    bits<1> idx;
7761    bits<1> idx2;
7762    let Inst{20} = idx;
7763    let Inst{19-16} = 0b1000;
7764    let Inst{14} = idx2;
7765    let Inst{13-11} = {?,?,?};
7766  }
7767
7768  // For all forms of the INS instruction, the "mov" mnemonic is the
7769  // preferred alias. Why they didn't just call the instruction "mov" in
7770  // the first place is a very good question indeed...
7771  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7772                         GPR32, VectorIndexB>;
7773  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7774                         GPR32, VectorIndexH>;
7775  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7776                         GPR32, VectorIndexS>;
7777  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7778                         GPR64, VectorIndexD>;
7779
7780  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7781                         VectorIndexB>;
7782  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7783                         VectorIndexH>;
7784  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7785                         VectorIndexS>;
7786  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7787                         VectorIndexD>;
7788}
7789
7790//----------------------------------------------------------------------------
7791// AdvSIMD TBL/TBX
7792//----------------------------------------------------------------------------
7793
7794let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7795class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7796                          RegisterOperand listtype, string asm, string kind>
7797  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7798       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7799    Sched<[!if(Q, WriteVq, WriteVd)]> {
7800  bits<5> Vd;
7801  bits<5> Vn;
7802  bits<5> Vm;
7803  let Inst{31}    = 0;
7804  let Inst{30}    = Q;
7805  let Inst{29-21} = 0b001110000;
7806  let Inst{20-16} = Vm;
7807  let Inst{15}    = 0;
7808  let Inst{14-13} = len;
7809  let Inst{12}    = op;
7810  let Inst{11-10} = 0b00;
7811  let Inst{9-5}   = Vn;
7812  let Inst{4-0}   = Vd;
7813}
7814
7815let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7816class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7817                          RegisterOperand listtype, string asm, string kind>
7818  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7819       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7820    Sched<[!if(Q, WriteVq, WriteVd)]> {
7821  bits<5> Vd;
7822  bits<5> Vn;
7823  bits<5> Vm;
7824  let Inst{31}    = 0;
7825  let Inst{30}    = Q;
7826  let Inst{29-21} = 0b001110000;
7827  let Inst{20-16} = Vm;
7828  let Inst{15}    = 0;
7829  let Inst{14-13} = len;
7830  let Inst{12}    = op;
7831  let Inst{11-10} = 0b00;
7832  let Inst{9-5}   = Vn;
7833  let Inst{4-0}   = Vd;
7834}
7835
7836class SIMDTableLookupAlias<string asm, Instruction inst,
7837                          RegisterOperand vectype, RegisterOperand listtype>
7838    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7839                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7840
7841multiclass SIMDTableLookup<bit op, string asm> {
7842  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7843                                      asm, ".8b">;
7844  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7845                                      asm, ".8b">;
7846  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7847                                      asm, ".8b">;
7848  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7849                                      asm, ".8b">;
7850  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7851                                      asm, ".16b">;
7852  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7853                                      asm, ".16b">;
7854  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7855                                      asm, ".16b">;
7856  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7857                                      asm, ".16b">;
7858
7859  def : SIMDTableLookupAlias<asm # ".8b",
7860                         !cast<Instruction>(NAME#"v8i8One"),
7861                         V64, VecListOne128>;
7862  def : SIMDTableLookupAlias<asm # ".8b",
7863                         !cast<Instruction>(NAME#"v8i8Two"),
7864                         V64, VecListTwo128>;
7865  def : SIMDTableLookupAlias<asm # ".8b",
7866                         !cast<Instruction>(NAME#"v8i8Three"),
7867                         V64, VecListThree128>;
7868  def : SIMDTableLookupAlias<asm # ".8b",
7869                         !cast<Instruction>(NAME#"v8i8Four"),
7870                         V64, VecListFour128>;
7871  def : SIMDTableLookupAlias<asm # ".16b",
7872                         !cast<Instruction>(NAME#"v16i8One"),
7873                         V128, VecListOne128>;
7874  def : SIMDTableLookupAlias<asm # ".16b",
7875                         !cast<Instruction>(NAME#"v16i8Two"),
7876                         V128, VecListTwo128>;
7877  def : SIMDTableLookupAlias<asm # ".16b",
7878                         !cast<Instruction>(NAME#"v16i8Three"),
7879                         V128, VecListThree128>;
7880  def : SIMDTableLookupAlias<asm # ".16b",
7881                         !cast<Instruction>(NAME#"v16i8Four"),
7882                         V128, VecListFour128>;
7883}
7884
7885multiclass SIMDTableLookupTied<bit op, string asm> {
7886  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7887                                      asm, ".8b">;
7888  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7889                                      asm, ".8b">;
7890  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7891                                      asm, ".8b">;
7892  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7893                                      asm, ".8b">;
7894  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7895                                      asm, ".16b">;
7896  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7897                                      asm, ".16b">;
7898  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7899                                      asm, ".16b">;
7900  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7901                                      asm, ".16b">;
7902
7903  def : SIMDTableLookupAlias<asm # ".8b",
7904                         !cast<Instruction>(NAME#"v8i8One"),
7905                         V64, VecListOne128>;
7906  def : SIMDTableLookupAlias<asm # ".8b",
7907                         !cast<Instruction>(NAME#"v8i8Two"),
7908                         V64, VecListTwo128>;
7909  def : SIMDTableLookupAlias<asm # ".8b",
7910                         !cast<Instruction>(NAME#"v8i8Three"),
7911                         V64, VecListThree128>;
7912  def : SIMDTableLookupAlias<asm # ".8b",
7913                         !cast<Instruction>(NAME#"v8i8Four"),
7914                         V64, VecListFour128>;
7915  def : SIMDTableLookupAlias<asm # ".16b",
7916                         !cast<Instruction>(NAME#"v16i8One"),
7917                         V128, VecListOne128>;
7918  def : SIMDTableLookupAlias<asm # ".16b",
7919                         !cast<Instruction>(NAME#"v16i8Two"),
7920                         V128, VecListTwo128>;
7921  def : SIMDTableLookupAlias<asm # ".16b",
7922                         !cast<Instruction>(NAME#"v16i8Three"),
7923                         V128, VecListThree128>;
7924  def : SIMDTableLookupAlias<asm # ".16b",
7925                         !cast<Instruction>(NAME#"v16i8Four"),
7926                         V128, VecListFour128>;
7927}
7928
7929
7930//----------------------------------------------------------------------------
7931// AdvSIMD scalar DUP
7932//----------------------------------------------------------------------------
7933let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7934class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
7935                        string asm, string kind, Operand idxtype>
7936  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
7937       "{\t$dst, $src" # kind # "$idx" #
7938       "|\t$dst, $src$idx}", "", []>,
7939    Sched<[WriteVd]> {
7940  bits<5> dst;
7941  bits<5> src;
7942  let Inst{31-21} = 0b01011110000;
7943  let Inst{15-10} = 0b000001;
7944  let Inst{9-5}   = src;
7945  let Inst{4-0}   = dst;
7946}
7947
7948class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
7949      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7950    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7951                    # "|\t$dst, $src$index}",
7952                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7953
7954
7955multiclass SIMDScalarDUP<string asm> {
7956  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
7957    bits<4> idx;
7958    let Inst{20-17} = idx;
7959    let Inst{16} = 1;
7960  }
7961  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
7962    bits<3> idx;
7963    let Inst{20-18} = idx;
7964    let Inst{17-16} = 0b10;
7965  }
7966  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
7967    bits<2> idx;
7968    let Inst{20-19} = idx;
7969    let Inst{18-16} = 0b100;
7970  }
7971  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
7972    bits<1> idx;
7973    let Inst{20} = idx;
7974    let Inst{19-16} = 0b1000;
7975  }
7976
7977  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7978                                                          VectorIndexD:$idx)))),
7979            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7980
7981  // 'DUP' mnemonic aliases.
7982  def : SIMDScalarDUPAlias<"dup", ".b",
7983                           !cast<Instruction>(NAME#"i8"),
7984                           FPR8, V128, VectorIndexB>;
7985  def : SIMDScalarDUPAlias<"dup", ".h",
7986                           !cast<Instruction>(NAME#"i16"),
7987                           FPR16, V128, VectorIndexH>;
7988  def : SIMDScalarDUPAlias<"dup", ".s",
7989                           !cast<Instruction>(NAME#"i32"),
7990                           FPR32, V128, VectorIndexS>;
7991  def : SIMDScalarDUPAlias<"dup", ".d",
7992                           !cast<Instruction>(NAME#"i64"),
7993                           FPR64, V128, VectorIndexD>;
7994}
7995
7996//----------------------------------------------------------------------------
7997// AdvSIMD modified immediate instructions
7998//----------------------------------------------------------------------------
7999
8000class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
8001                          string asm, string op_string,
8002                          string cstr, list<dag> pattern>
8003  : I<oops, iops, asm, op_string, cstr, pattern>,
8004    Sched<[!if(Q, WriteVq, WriteVd)]> {
8005  bits<5> Rd;
8006  bits<8> imm8;
8007  let Inst{31}    = 0;
8008  let Inst{30}    = Q;
8009  let Inst{29}    = op;
8010  let Inst{28-19} = 0b0111100000;
8011  let Inst{18-16} = imm8{7-5};
8012  let Inst{11} = op2;
8013  let Inst{10} = 1;
8014  let Inst{9-5}   = imm8{4-0};
8015  let Inst{4-0}   = Rd;
8016}
8017
8018class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
8019                                Operand immtype, dag opt_shift_iop,
8020                                string opt_shift, string asm, string kind,
8021                                list<dag> pattern>
8022  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
8023                        !con((ins immtype:$imm8), opt_shift_iop), asm,
8024                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
8025                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8026                        "", pattern> {
8027  let DecoderMethod = "DecodeModImmInstruction";
8028}
8029
8030class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
8031                                Operand immtype, dag opt_shift_iop,
8032                                string opt_shift, string asm, string kind,
8033                                list<dag> pattern>
8034  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
8035                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
8036                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
8037                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8038                        "$Rd = $dst", pattern> {
8039  let DecoderMethod = "DecodeModImmTiedInstruction";
8040}
8041
8042class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
8043                                     RegisterOperand vectype, string asm,
8044                                     string kind, list<dag> pattern>
8045  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8046                              (ins logical_vec_shift:$shift),
8047                              "$shift", asm, kind, pattern> {
8048  bits<2> shift;
8049  let Inst{15}    = b15_b12{1};
8050  let Inst{14-13} = shift;
8051  let Inst{12}    = b15_b12{0};
8052}
8053
8054class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
8055                                     RegisterOperand vectype, string asm,
8056                                     string kind, list<dag> pattern>
8057  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8058                              (ins logical_vec_shift:$shift),
8059                              "$shift", asm, kind, pattern> {
8060  bits<2> shift;
8061  let Inst{15}    = b15_b12{1};
8062  let Inst{14-13} = shift;
8063  let Inst{12}    = b15_b12{0};
8064}
8065
8066
8067class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
8068                                         RegisterOperand vectype, string asm,
8069                                         string kind, list<dag> pattern>
8070  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8071                              (ins logical_vec_hw_shift:$shift),
8072                              "$shift", asm, kind, pattern> {
8073  bits<2> shift;
8074  let Inst{15} = b15_b12{1};
8075  let Inst{14} = 0;
8076  let Inst{13} = shift{0};
8077  let Inst{12} = b15_b12{0};
8078}
8079
8080class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
8081                                         RegisterOperand vectype, string asm,
8082                                         string kind, list<dag> pattern>
8083  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8084                              (ins logical_vec_hw_shift:$shift),
8085                              "$shift", asm, kind, pattern> {
8086  bits<2> shift;
8087  let Inst{15} = b15_b12{1};
8088  let Inst{14} = 0;
8089  let Inst{13} = shift{0};
8090  let Inst{12} = b15_b12{0};
8091}
8092
8093multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
8094                                      string asm> {
8095  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
8096                                                 asm, ".4h", []>;
8097  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
8098                                                 asm, ".8h", []>;
8099
8100  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
8101                                             asm, ".2s", []>;
8102  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
8103                                             asm, ".4s", []>;
8104}
8105
8106multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
8107                                      bits<2> w_cmode, string asm,
8108                                      SDNode OpNode> {
8109  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
8110                                                 asm, ".4h",
8111             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
8112                                             imm0_255:$imm8,
8113                                             (i32 imm:$shift)))]>;
8114  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
8115                                                 asm, ".8h",
8116             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
8117                                              imm0_255:$imm8,
8118                                              (i32 imm:$shift)))]>;
8119
8120  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
8121                                             asm, ".2s",
8122             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
8123                                             imm0_255:$imm8,
8124                                             (i32 imm:$shift)))]>;
8125  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
8126                                             asm, ".4s",
8127             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
8128                                              imm0_255:$imm8,
8129                                              (i32 imm:$shift)))]>;
8130}
8131
8132class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
8133                             RegisterOperand vectype, string asm,
8134                             string kind, list<dag> pattern>
8135  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8136                              (ins move_vec_shift:$shift),
8137                              "$shift", asm, kind, pattern> {
8138  bits<1> shift;
8139  let Inst{15-13} = cmode{3-1};
8140  let Inst{12}    = shift;
8141}
8142
8143class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
8144                                   RegisterOperand vectype,
8145                                   Operand imm_type, string asm,
8146                                   string kind, list<dag> pattern>
8147  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
8148                              asm, kind, pattern> {
8149  let Inst{15-12} = cmode;
8150}
8151
8152class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
8153                                   list<dag> pattern>
8154  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
8155                        "\t$Rd, $imm8", "", pattern> {
8156  let Inst{15-12} = cmode;
8157  let DecoderMethod = "DecodeModImmInstruction";
8158}
8159
8160//----------------------------------------------------------------------------
8161// AdvSIMD indexed element
8162//----------------------------------------------------------------------------
8163
8164let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8165class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8166                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8167                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8168                      string apple_kind, string dst_kind, string lhs_kind,
8169                      string rhs_kind, list<dag> pattern>
8170  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8171      asm,
8172      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8173      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8174    Sched<[WriteVd]> {
8175  bits<5> Rd;
8176  bits<5> Rn;
8177  bits<5> Rm;
8178
8179  let Inst{31}    = 0;
8180  let Inst{30}    = Q;
8181  let Inst{29}    = U;
8182  let Inst{28}    = Scalar;
8183  let Inst{27-24} = 0b1111;
8184  let Inst{23-22} = size;
8185  // Bit 21 must be set by the derived class.
8186  let Inst{20-16} = Rm;
8187  let Inst{15-12} = opc;
8188  // Bit 11 must be set by the derived class.
8189  let Inst{10}    = 0;
8190  let Inst{9-5}   = Rn;
8191  let Inst{4-0}   = Rd;
8192}
8193
8194let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8195class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8196                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8197                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8198                      string apple_kind, string dst_kind, string lhs_kind,
8199                      string rhs_kind, list<dag> pattern>
8200  : I<(outs dst_reg:$dst),
8201      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8202      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8203      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8204    Sched<[WriteVd]> {
8205  bits<5> Rd;
8206  bits<5> Rn;
8207  bits<5> Rm;
8208
8209  let Inst{31}    = 0;
8210  let Inst{30}    = Q;
8211  let Inst{29}    = U;
8212  let Inst{28}    = Scalar;
8213  let Inst{27-24} = 0b1111;
8214  let Inst{23-22} = size;
8215  // Bit 21 must be set by the derived class.
8216  let Inst{20-16} = Rm;
8217  let Inst{15-12} = opc;
8218  // Bit 11 must be set by the derived class.
8219  let Inst{10}    = 0;
8220  let Inst{9-5}   = Rn;
8221  let Inst{4-0}   = Rd;
8222}
8223
8224
8225//----------------------------------------------------------------------------
8226// Armv8.6 BFloat16 Extension
8227//----------------------------------------------------------------------------
8228let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8229
8230class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8231                                   string kind2, RegisterOperand RegType,
8232                                   ValueType AccumType, ValueType InputType>
8233  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8234                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8235                                            (InputType RegType:$Rn),
8236                                            (InputType RegType:$Rm)))]> {
8237  let AsmString = !strconcat(asm,
8238                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8239                               ", $Rm" # kind2 # "}");
8240}
8241
8242multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8243  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8244                                           v2f32, v4bf16>;
8245  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8246                                           v4f32, v8bf16>;
8247}
8248
8249class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8250                                      string dst_kind, string lhs_kind,
8251                                      string rhs_kind,
8252                                      RegisterOperand RegType,
8253                                      ValueType AccumType,
8254                                      ValueType InputType>
8255  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8256                        RegType, RegType, V128, VectorIndexS,
8257                        asm, "", dst_kind, lhs_kind, rhs_kind,
8258        [(set (AccumType RegType:$dst),
8259              (AccumType (int_aarch64_neon_bfdot
8260                                 (AccumType RegType:$Rd),
8261                                 (InputType RegType:$Rn),
8262                                 (InputType (bitconvert (AccumType
8263                                    (AArch64duplane32 (v4f32 V128:$Rm),
8264                                        VectorIndexS:$idx)))))))]> {
8265
8266  bits<2> idx;
8267  let Inst{21}    = idx{0};  // L
8268  let Inst{11}    = idx{1};  // H
8269}
8270
8271multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8272
8273  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8274                                               ".2h", V64, v2f32, v4bf16>;
8275  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8276                                              ".2h", V128, v4f32, v8bf16>;
8277}
8278
8279let mayRaiseFPException = 1, Uses = [FPCR] in
8280class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8281  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8282              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8283                                               (v8bf16 V128:$Rn),
8284                                               (v8bf16 V128:$Rm)))]> {
8285  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8286}
8287
8288let mayRaiseFPException = 1, Uses = [FPCR] in
8289class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8290  : I<(outs V128:$dst),
8291      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8292      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8293          [(set (v4f32 V128:$dst),
8294                (v4f32 (OpNode (v4f32 V128:$Rd),
8295                               (v8bf16 V128:$Rn),
8296                               (v8bf16
8297                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8298                                      VectorIndexH:$idx)))))]>,
8299    Sched<[WriteVq]> {
8300  bits<5> Rd;
8301  bits<5> Rn;
8302  bits<4> Rm;
8303  bits<3> idx;
8304
8305  let Inst{31}    = 0;
8306  let Inst{30}    = Q;
8307  let Inst{29-22} = 0b00111111;
8308  let Inst{21-20} = idx{1-0};
8309  let Inst{19-16} = Rm;
8310  let Inst{15-12} = 0b1111;
8311  let Inst{11}    = idx{2};   // H
8312  let Inst{10}    = 0;
8313  let Inst{9-5}   = Rn;
8314  let Inst{4-0}   = Rd;
8315}
8316
8317class SIMDThreeSameVectorBF16MatrixMul<string asm>
8318  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8319                                V128, asm, ".4s",
8320                          [(set (v4f32 V128:$dst),
8321                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8322                                                         (v8bf16 V128:$Rn),
8323                                                         (v8bf16 V128:$Rm)))]> {
8324  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8325                                    ", $Rm", ".8h", "}");
8326}
8327
8328let mayRaiseFPException = 1, Uses = [FPCR] in
8329class SIMD_BFCVTN
8330  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8331                           "bfcvtn", ".4h", ".4s",
8332    [(set (v8bf16 V128:$Rd),
8333          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8334
8335let mayRaiseFPException = 1, Uses = [FPCR] in
8336class SIMD_BFCVTN2
8337  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8338                           "bfcvtn2", ".8h", ".4s",
8339    [(set (v8bf16 V128:$dst),
8340          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8341
8342let mayRaiseFPException = 1, Uses = [FPCR] in
8343class BF16ToSinglePrecision<string asm>
8344  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8345    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8346    Sched<[WriteFCvt]> {
8347  bits<5> Rd;
8348  bits<5> Rn;
8349  let Inst{31-10} = 0b0001111001100011010000;
8350  let Inst{9-5}   = Rn;
8351  let Inst{4-0}   = Rd;
8352}
8353} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8354
8355//----------------------------------------------------------------------------
8356// Armv8.6 Matrix Multiply Extension
8357//----------------------------------------------------------------------------
8358
8359class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8360  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8361              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8362                                               (v16i8 V128:$Rn),
8363                                               (v16i8 V128:$Rm)))]> {
8364  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8365}
8366
8367//----------------------------------------------------------------------------
8368// ARMv8.2-A Dot Product Instructions (Indexed)
8369class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8370                                      string dst_kind, string lhs_kind, string rhs_kind,
8371                                      RegisterOperand RegType,
8372                                      ValueType AccumType, ValueType InputType,
8373                                      SDPatternOperator OpNode> :
8374        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8375                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8376        [(set (AccumType RegType:$dst),
8377              (AccumType (OpNode (AccumType RegType:$Rd),
8378                                 (InputType RegType:$Rn),
8379                                 (InputType (bitconvert (AccumType
8380                                    (AArch64duplane32 (v4i32 V128:$Rm),
8381                                        VectorIndexS:$idx)))))))]> {
8382  bits<2> idx;
8383  let Inst{21}    = idx{0};  // L
8384  let Inst{11}    = idx{1};  // H
8385}
8386
8387multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8388                                       SDPatternOperator OpNode> {
8389  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8390                                              V64, v2i32, v8i8, OpNode>;
8391  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8392                                              V128, v4i32, v16i8, OpNode>;
8393}
8394
8395// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8396let mayRaiseFPException = 1, Uses = [FPCR] in
8397class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8398                                      string dst_kind, string lhs_kind,
8399                                      string rhs_kind, RegisterOperand RegType,
8400                                      ValueType AccumType, ValueType InputType,
8401                                      SDPatternOperator OpNode> :
8402        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8403                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8404          [(set (AccumType RegType:$dst),
8405                (AccumType (OpNode (AccumType RegType:$Rd),
8406                                   (InputType RegType:$Rn),
8407                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8408                                                VectorIndexH:$idx)))))]> {
8409  // idx = H:L:M
8410  bits<3> idx;
8411  let Inst{11} = idx{2}; // H
8412  let Inst{21} = idx{1}; // L
8413  let Inst{20} = idx{0}; // M
8414}
8415
8416multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8417                                       SDPatternOperator OpNode> {
8418  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8419                                              V64, v2f32, v4f16, OpNode>;
8420  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8421                                              V128, v4f32, v8f16, OpNode>;
8422}
8423
8424let mayRaiseFPException = 1, Uses = [FPCR] in
8425multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8426                         SDPatternOperator OpNode> {
8427  let Predicates = [HasNEON, HasFullFP16] in {
8428  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8429                                      V64, V64,
8430                                      V128_lo, VectorIndexH,
8431                                      asm, ".4h", ".4h", ".4h", ".h",
8432    [(set (v4f16 V64:$Rd),
8433        (OpNode (v4f16 V64:$Rn),
8434         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8435    bits<3> idx;
8436    let Inst{11} = idx{2};
8437    let Inst{21} = idx{1};
8438    let Inst{20} = idx{0};
8439  }
8440
8441  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8442                                      V128, V128,
8443                                      V128_lo, VectorIndexH,
8444                                      asm, ".8h", ".8h", ".8h", ".h",
8445    [(set (v8f16 V128:$Rd),
8446        (OpNode (v8f16 V128:$Rn),
8447         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8448    bits<3> idx;
8449    let Inst{11} = idx{2};
8450    let Inst{21} = idx{1};
8451    let Inst{20} = idx{0};
8452  }
8453  } // Predicates = [HasNEON, HasFullFP16]
8454
8455  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8456                                      V64, V64,
8457                                      V128, VectorIndexS,
8458                                      asm, ".2s", ".2s", ".2s", ".s",
8459    [(set (v2f32 V64:$Rd),
8460        (OpNode (v2f32 V64:$Rn),
8461         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8462    bits<2> idx;
8463    let Inst{11} = idx{1};
8464    let Inst{21} = idx{0};
8465  }
8466
8467  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8468                                      V128, V128,
8469                                      V128, VectorIndexS,
8470                                      asm, ".4s", ".4s", ".4s", ".s",
8471    [(set (v4f32 V128:$Rd),
8472        (OpNode (v4f32 V128:$Rn),
8473         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8474    bits<2> idx;
8475    let Inst{11} = idx{1};
8476    let Inst{21} = idx{0};
8477  }
8478
8479  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8480                                      V128, V128,
8481                                      V128, VectorIndexD,
8482                                      asm, ".2d", ".2d", ".2d", ".d",
8483    [(set (v2f64 V128:$Rd),
8484        (OpNode (v2f64 V128:$Rn),
8485         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8486    bits<1> idx;
8487    let Inst{11} = idx{0};
8488    let Inst{21} = 0;
8489  }
8490
8491  let Predicates = [HasNEON, HasFullFP16] in {
8492  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8493                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8494                                      asm, ".h", "", "", ".h",
8495    [(set (f16 FPR16Op:$Rd),
8496          (OpNode (f16 FPR16Op:$Rn),
8497                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8498                                       VectorIndexH:$idx))))]> {
8499    bits<3> idx;
8500    let Inst{11} = idx{2};
8501    let Inst{21} = idx{1};
8502    let Inst{20} = idx{0};
8503  }
8504  } // Predicates = [HasNEON, HasFullFP16]
8505
8506  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8507                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8508                                      asm, ".s", "", "", ".s",
8509    [(set (f32 FPR32Op:$Rd),
8510          (OpNode (f32 FPR32Op:$Rn),
8511                  (f32 (vector_extract (v4f32 V128:$Rm),
8512                                       VectorIndexS:$idx))))]> {
8513    bits<2> idx;
8514    let Inst{11} = idx{1};
8515    let Inst{21} = idx{0};
8516  }
8517
8518  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8519                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8520                                      asm, ".d", "", "", ".d",
8521    [(set (f64 FPR64Op:$Rd),
8522          (OpNode (f64 FPR64Op:$Rn),
8523                  (f64 (vector_extract (v2f64 V128:$Rm),
8524                                       VectorIndexD:$idx))))]> {
8525    bits<1> idx;
8526    let Inst{11} = idx{0};
8527    let Inst{21} = 0;
8528  }
8529}
8530
8531multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8532  let Predicates = [HasNEON, HasFullFP16] in {
8533  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8534  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8535                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8536                                           VectorIndexH:$idx))),
8537            (!cast<Instruction>(INST # "v8i16_indexed")
8538                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8539  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8540                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8541            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8542                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8543
8544  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8545                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8546                                           VectorIndexH:$idx))),
8547            (!cast<Instruction>(INST # "v4i16_indexed")
8548                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8549  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8550                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8551            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8552                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8553
8554  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8555                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8556            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8557                V128_lo:$Rm, VectorIndexH:$idx)>;
8558  } // Predicates = [HasNEON, HasFullFP16]
8559
8560  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8561  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8562                           (AArch64duplane32 (v4f32 V128:$Rm),
8563                                           VectorIndexS:$idx))),
8564            (!cast<Instruction>(INST # v2i32_indexed)
8565                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8566  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8567                           (AArch64dup (f32 FPR32Op:$Rm)))),
8568            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8569                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8570
8571
8572  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8573  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8574                           (AArch64duplane32 (v4f32 V128:$Rm),
8575                                           VectorIndexS:$idx))),
8576            (!cast<Instruction>(INST # "v4i32_indexed")
8577                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8578  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8579                           (AArch64dup (f32 FPR32Op:$Rm)))),
8580            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8581                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8582
8583  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8584  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8585                           (AArch64duplane64 (v2f64 V128:$Rm),
8586                                           VectorIndexD:$idx))),
8587            (!cast<Instruction>(INST # "v2i64_indexed")
8588                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8589  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8590                           (AArch64dup (f64 FPR64Op:$Rm)))),
8591            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8592                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8593
8594  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8595  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8596                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8597            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8598                V128:$Rm, VectorIndexS:$idx)>;
8599
8600  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8601  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8602                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8603            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8604                V128:$Rm, VectorIndexD:$idx)>;
8605}
8606
8607let mayRaiseFPException = 1, Uses = [FPCR] in
8608multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8609  let Predicates = [HasNEON, HasFullFP16] in {
8610  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8611                                          V128_lo, VectorIndexH,
8612                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8613    bits<3> idx;
8614    let Inst{11} = idx{2};
8615    let Inst{21} = idx{1};
8616    let Inst{20} = idx{0};
8617  }
8618
8619  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8620                                          V128, V128,
8621                                          V128_lo, VectorIndexH,
8622                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8623    bits<3> idx;
8624    let Inst{11} = idx{2};
8625    let Inst{21} = idx{1};
8626    let Inst{20} = idx{0};
8627  }
8628  } // Predicates = [HasNEON, HasFullFP16]
8629
8630  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8631                                          V128, VectorIndexS,
8632                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8633    bits<2> idx;
8634    let Inst{11} = idx{1};
8635    let Inst{21} = idx{0};
8636  }
8637
8638  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8639                                      V128, V128,
8640                                      V128, VectorIndexS,
8641                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8642    bits<2> idx;
8643    let Inst{11} = idx{1};
8644    let Inst{21} = idx{0};
8645  }
8646
8647  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8648                                      V128, V128,
8649                                      V128, VectorIndexD,
8650                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8651    bits<1> idx;
8652    let Inst{11} = idx{0};
8653    let Inst{21} = 0;
8654  }
8655
8656  let Predicates = [HasNEON, HasFullFP16] in {
8657  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8658                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8659                                      asm, ".h", "", "", ".h", []> {
8660    bits<3> idx;
8661    let Inst{11} = idx{2};
8662    let Inst{21} = idx{1};
8663    let Inst{20} = idx{0};
8664  }
8665  } // Predicates = [HasNEON, HasFullFP16]
8666
8667  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8668                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8669                                      asm, ".s", "", "", ".s", []> {
8670    bits<2> idx;
8671    let Inst{11} = idx{1};
8672    let Inst{21} = idx{0};
8673  }
8674
8675  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8676                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8677                                      asm, ".d", "", "", ".d", []> {
8678    bits<1> idx;
8679    let Inst{11} = idx{0};
8680    let Inst{21} = 0;
8681  }
8682}
8683
8684multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8685                                 SDPatternOperator OpNodeLaneQ> {
8686
8687  def : Pat<(v4i16 (OpNodeLane
8688                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8689                     VectorIndexS32b:$idx)),
8690            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8691              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8692              (UImmS1XForm $idx))>;
8693
8694  def : Pat<(v4i16 (OpNodeLaneQ
8695                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8696                     VectorIndexH32b:$idx)),
8697            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8698              (UImmS1XForm $idx))>;
8699
8700  def : Pat<(v8i16 (OpNodeLane
8701                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8702                     VectorIndexS32b:$idx)),
8703            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8704              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8705              (UImmS1XForm $idx))>;
8706
8707  def : Pat<(v8i16 (OpNodeLaneQ
8708                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8709                     VectorIndexH32b:$idx)),
8710            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8711              (UImmS1XForm $idx))>;
8712
8713  def : Pat<(v2i32 (OpNodeLane
8714                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8715                     VectorIndexD32b:$idx)),
8716            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8717              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8718              (UImmS1XForm $idx))>;
8719
8720  def : Pat<(v2i32 (OpNodeLaneQ
8721                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8722                     VectorIndexS32b:$idx)),
8723            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8724              (UImmS1XForm $idx))>;
8725
8726  def : Pat<(v4i32 (OpNodeLane
8727                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8728                     VectorIndexD32b:$idx)),
8729            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8730              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8731              (UImmS1XForm $idx))>;
8732
8733  def : Pat<(v4i32 (OpNodeLaneQ
8734                     (v4i32 V128:$Rn),
8735                     (v4i32 V128:$Rm),
8736                     VectorIndexS32b:$idx)),
8737            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8738              (UImmS1XForm $idx))>;
8739
8740}
8741
8742multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8743                         SDPatternOperator OpNode> {
8744  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8745                                      V128_lo, VectorIndexH,
8746                                      asm, ".4h", ".4h", ".4h", ".h",
8747    [(set (v4i16 V64:$Rd),
8748        (OpNode (v4i16 V64:$Rn),
8749         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8750    bits<3> idx;
8751    let Inst{11} = idx{2};
8752    let Inst{21} = idx{1};
8753    let Inst{20} = idx{0};
8754  }
8755
8756  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8757                                      V128, V128,
8758                                      V128_lo, VectorIndexH,
8759                                      asm, ".8h", ".8h", ".8h", ".h",
8760    [(set (v8i16 V128:$Rd),
8761       (OpNode (v8i16 V128:$Rn),
8762         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8763    bits<3> idx;
8764    let Inst{11} = idx{2};
8765    let Inst{21} = idx{1};
8766    let Inst{20} = idx{0};
8767  }
8768
8769  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8770                                      V64, V64,
8771                                      V128, VectorIndexS,
8772                                      asm, ".2s", ".2s", ".2s",  ".s",
8773    [(set (v2i32 V64:$Rd),
8774       (OpNode (v2i32 V64:$Rn),
8775          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8776    bits<2> idx;
8777    let Inst{11} = idx{1};
8778    let Inst{21} = idx{0};
8779  }
8780
8781  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8782                                      V128, V128,
8783                                      V128, VectorIndexS,
8784                                      asm, ".4s", ".4s", ".4s", ".s",
8785    [(set (v4i32 V128:$Rd),
8786       (OpNode (v4i32 V128:$Rn),
8787          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8788    bits<2> idx;
8789    let Inst{11} = idx{1};
8790    let Inst{21} = idx{0};
8791  }
8792
8793  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8794                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8795                                      asm, ".h", "", "", ".h", []> {
8796    bits<3> idx;
8797    let Inst{11} = idx{2};
8798    let Inst{21} = idx{1};
8799    let Inst{20} = idx{0};
8800  }
8801
8802  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8803                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8804                                      asm, ".s", "", "", ".s",
8805      [(set (i32 FPR32Op:$Rd),
8806            (OpNode FPR32Op:$Rn,
8807                    (i32 (vector_extract (v4i32 V128:$Rm),
8808                                         VectorIndexS:$idx))))]> {
8809    bits<2> idx;
8810    let Inst{11} = idx{1};
8811    let Inst{21} = idx{0};
8812  }
8813}
8814
8815multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8816                               SDPatternOperator OpNode> {
8817  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8818                                      V64, V64,
8819                                      V128_lo, VectorIndexH,
8820                                      asm, ".4h", ".4h", ".4h", ".h",
8821    [(set (v4i16 V64:$Rd),
8822        (OpNode (v4i16 V64:$Rn),
8823         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8824    bits<3> idx;
8825    let Inst{11} = idx{2};
8826    let Inst{21} = idx{1};
8827    let Inst{20} = idx{0};
8828  }
8829
8830  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8831                                      V128, V128,
8832                                      V128_lo, VectorIndexH,
8833                                      asm, ".8h", ".8h", ".8h", ".h",
8834    [(set (v8i16 V128:$Rd),
8835       (OpNode (v8i16 V128:$Rn),
8836         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8837    bits<3> idx;
8838    let Inst{11} = idx{2};
8839    let Inst{21} = idx{1};
8840    let Inst{20} = idx{0};
8841  }
8842
8843  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8844                                      V64, V64,
8845                                      V128, VectorIndexS,
8846                                      asm, ".2s", ".2s", ".2s", ".s",
8847    [(set (v2i32 V64:$Rd),
8848       (OpNode (v2i32 V64:$Rn),
8849          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8850    bits<2> idx;
8851    let Inst{11} = idx{1};
8852    let Inst{21} = idx{0};
8853  }
8854
8855  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8856                                      V128, V128,
8857                                      V128, VectorIndexS,
8858                                      asm, ".4s", ".4s", ".4s", ".s",
8859    [(set (v4i32 V128:$Rd),
8860       (OpNode (v4i32 V128:$Rn),
8861          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8862    bits<2> idx;
8863    let Inst{11} = idx{1};
8864    let Inst{21} = idx{0};
8865  }
8866}
8867
8868multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8869                                   SDPatternOperator OpNode> {
8870  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8871                                          V128_lo, VectorIndexH,
8872                                          asm, ".4h", ".4h", ".4h", ".h",
8873    [(set (v4i16 V64:$dst),
8874        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8875         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8876    bits<3> idx;
8877    let Inst{11} = idx{2};
8878    let Inst{21} = idx{1};
8879    let Inst{20} = idx{0};
8880  }
8881
8882  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8883                                      V128, V128,
8884                                      V128_lo, VectorIndexH,
8885                                      asm, ".8h", ".8h", ".8h", ".h",
8886    [(set (v8i16 V128:$dst),
8887       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8888         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8889    bits<3> idx;
8890    let Inst{11} = idx{2};
8891    let Inst{21} = idx{1};
8892    let Inst{20} = idx{0};
8893  }
8894
8895  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8896                                      V64, V64,
8897                                      V128, VectorIndexS,
8898                                      asm, ".2s", ".2s", ".2s", ".s",
8899    [(set (v2i32 V64:$dst),
8900       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8901          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8902    bits<2> idx;
8903    let Inst{11} = idx{1};
8904    let Inst{21} = idx{0};
8905  }
8906
8907  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8908                                      V128, V128,
8909                                      V128, VectorIndexS,
8910                                      asm, ".4s", ".4s", ".4s", ".s",
8911    [(set (v4i32 V128:$dst),
8912       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8913          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8914    bits<2> idx;
8915    let Inst{11} = idx{1};
8916    let Inst{21} = idx{0};
8917  }
8918}
8919
8920multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8921                             SDPatternOperator OpNode> {
8922  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8923                                      V128, V64,
8924                                      V128_lo, VectorIndexH,
8925                                      asm, ".4s", ".4s", ".4h", ".h",
8926    [(set (v4i32 V128:$Rd),
8927        (OpNode (v4i16 V64:$Rn),
8928         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8929    bits<3> idx;
8930    let Inst{11} = idx{2};
8931    let Inst{21} = idx{1};
8932    let Inst{20} = idx{0};
8933  }
8934
8935  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8936                                      V128, V128,
8937                                      V128_lo, VectorIndexH,
8938                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8939    [(set (v4i32 V128:$Rd),
8940          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8941                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8942
8943    bits<3> idx;
8944    let Inst{11} = idx{2};
8945    let Inst{21} = idx{1};
8946    let Inst{20} = idx{0};
8947  }
8948
8949  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8950                                      V128, V64,
8951                                      V128, VectorIndexS,
8952                                      asm, ".2d", ".2d", ".2s", ".s",
8953    [(set (v2i64 V128:$Rd),
8954        (OpNode (v2i32 V64:$Rn),
8955         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8956    bits<2> idx;
8957    let Inst{11} = idx{1};
8958    let Inst{21} = idx{0};
8959  }
8960
8961  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8962                                      V128, V128,
8963                                      V128, VectorIndexS,
8964                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8965    [(set (v2i64 V128:$Rd),
8966          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8967                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8968    bits<2> idx;
8969    let Inst{11} = idx{1};
8970    let Inst{21} = idx{0};
8971  }
8972
8973  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8974                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8975                                      asm, ".h", "", "", ".h", []> {
8976    bits<3> idx;
8977    let Inst{11} = idx{2};
8978    let Inst{21} = idx{1};
8979    let Inst{20} = idx{0};
8980  }
8981
8982  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8983                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8984                                      asm, ".s", "", "", ".s", []> {
8985    bits<2> idx;
8986    let Inst{11} = idx{1};
8987    let Inst{21} = idx{0};
8988  }
8989}
8990
8991multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8992                                       SDPatternOperator Accum> {
8993  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8994                                      V128, V64,
8995                                      V128_lo, VectorIndexH,
8996                                      asm, ".4s", ".4s", ".4h", ".h",
8997    [(set (v4i32 V128:$dst),
8998          (Accum (v4i32 V128:$Rd),
8999                 (v4i32 (int_aarch64_neon_sqdmull
9000                             (v4i16 V64:$Rn),
9001                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9002                                                    VectorIndexH:$idx))))))]> {
9003    bits<3> idx;
9004    let Inst{11} = idx{2};
9005    let Inst{21} = idx{1};
9006    let Inst{20} = idx{0};
9007  }
9008
9009  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9010                                      V128, V128,
9011                                      V128_lo, VectorIndexH,
9012                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9013    [(set (v4i32 V128:$dst),
9014          (Accum (v4i32 V128:$Rd),
9015                 (v4i32 (int_aarch64_neon_sqdmull
9016                            (extract_high_v8i16 (v8i16 V128:$Rn)),
9017                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
9018    bits<3> idx;
9019    let Inst{11} = idx{2};
9020    let Inst{21} = idx{1};
9021    let Inst{20} = idx{0};
9022  }
9023
9024  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9025                                      V128, V64,
9026                                      V128, VectorIndexS,
9027                                      asm, ".2d", ".2d", ".2s", ".s",
9028    [(set (v2i64 V128:$dst),
9029        (Accum (v2i64 V128:$Rd),
9030               (v2i64 (int_aarch64_neon_sqdmull
9031                          (v2i32 V64:$Rn),
9032                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9033                                                 VectorIndexS:$idx))))))]> {
9034    bits<2> idx;
9035    let Inst{11} = idx{1};
9036    let Inst{21} = idx{0};
9037  }
9038
9039  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9040                                      V128, V128,
9041                                      V128, VectorIndexS,
9042                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9043    [(set (v2i64 V128:$dst),
9044          (Accum (v2i64 V128:$Rd),
9045                 (v2i64 (int_aarch64_neon_sqdmull
9046                            (extract_high_v4i32 (v4i32 V128:$Rn)),
9047                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9048    bits<2> idx;
9049    let Inst{11} = idx{1};
9050    let Inst{21} = idx{0};
9051  }
9052
9053  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9054                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9055                                      asm, ".h", "", "", ".h", []> {
9056    bits<3> idx;
9057    let Inst{11} = idx{2};
9058    let Inst{21} = idx{1};
9059    let Inst{20} = idx{0};
9060  }
9061
9062  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9063                        (i32 (vector_extract
9064                                    (v4i32 (int_aarch64_neon_sqdmull
9065                                                (v4i16 V64:$Rn),
9066                                                (v4i16 V64:$Rm))),
9067                                    (i64 0))))),
9068            (!cast<Instruction>(NAME # v1i32_indexed)
9069                        FPR32Op:$Rd,
9070                        (EXTRACT_SUBREG V64:$Rn, hsub),
9071                        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rm, dsub),
9072                        (i64 0))>;
9073
9074  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9075                        (i32 (vector_extract
9076                                    (v4i32 (int_aarch64_neon_sqdmull
9077                                                (v4i16 V64:$Rn),
9078                                                (v4i16 (AArch64duplane16
9079                                                            (v8i16 V128_lo:$Rm),
9080                                                            VectorIndexH:$idx)))),
9081                                    (i64 0))))),
9082            (!cast<Instruction>(NAME # v1i32_indexed)
9083                        FPR32Op:$Rd,
9084                        (EXTRACT_SUBREG V64:$Rn, hsub),
9085                        V128_lo:$Rm,
9086                        VectorIndexH:$idx)>;
9087
9088  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9089                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9090                                      asm, ".s", "", "", ".s",
9091    [(set (i64 FPR64Op:$dst),
9092          (Accum (i64 FPR64Op:$Rd),
9093                 (i64 (int_aarch64_neon_sqdmulls_scalar
9094                            (i32 FPR32Op:$Rn),
9095                            (i32 (vector_extract (v4i32 V128:$Rm),
9096                                                 VectorIndexS:$idx))))))]> {
9097
9098    bits<2> idx;
9099    let Inst{11} = idx{1};
9100    let Inst{21} = idx{0};
9101  }
9102}
9103
9104multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
9105                                   SDPatternOperator OpNode> {
9106  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9107  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9108                                      V128, V64,
9109                                      V128_lo, VectorIndexH,
9110                                      asm, ".4s", ".4s", ".4h", ".h",
9111    [(set (v4i32 V128:$Rd),
9112        (OpNode (v4i16 V64:$Rn),
9113         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9114    bits<3> idx;
9115    let Inst{11} = idx{2};
9116    let Inst{21} = idx{1};
9117    let Inst{20} = idx{0};
9118  }
9119
9120  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9121                                      V128, V128,
9122                                      V128_lo, VectorIndexH,
9123                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9124    [(set (v4i32 V128:$Rd),
9125          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9126                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9127
9128    bits<3> idx;
9129    let Inst{11} = idx{2};
9130    let Inst{21} = idx{1};
9131    let Inst{20} = idx{0};
9132  }
9133
9134  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9135                                      V128, V64,
9136                                      V128, VectorIndexS,
9137                                      asm, ".2d", ".2d", ".2s", ".s",
9138    [(set (v2i64 V128:$Rd),
9139        (OpNode (v2i32 V64:$Rn),
9140         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9141    bits<2> idx;
9142    let Inst{11} = idx{1};
9143    let Inst{21} = idx{0};
9144  }
9145
9146  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9147                                      V128, V128,
9148                                      V128, VectorIndexS,
9149                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9150    [(set (v2i64 V128:$Rd),
9151          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9152                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9153    bits<2> idx;
9154    let Inst{11} = idx{1};
9155    let Inst{21} = idx{0};
9156  }
9157  }
9158}
9159
9160multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
9161                                       SDPatternOperator OpNode> {
9162  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9163  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9164                                      V128, V64,
9165                                      V128_lo, VectorIndexH,
9166                                      asm, ".4s", ".4s", ".4h", ".h",
9167    [(set (v4i32 V128:$dst),
9168        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
9169         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9170    bits<3> idx;
9171    let Inst{11} = idx{2};
9172    let Inst{21} = idx{1};
9173    let Inst{20} = idx{0};
9174  }
9175
9176  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9177                                      V128, V128,
9178                                      V128_lo, VectorIndexH,
9179                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9180    [(set (v4i32 V128:$dst),
9181          (OpNode (v4i32 V128:$Rd),
9182                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9183                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9184    bits<3> idx;
9185    let Inst{11} = idx{2};
9186    let Inst{21} = idx{1};
9187    let Inst{20} = idx{0};
9188  }
9189
9190  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9191                                      V128, V64,
9192                                      V128, VectorIndexS,
9193                                      asm, ".2d", ".2d", ".2s", ".s",
9194    [(set (v2i64 V128:$dst),
9195        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9196         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9197    bits<2> idx;
9198    let Inst{11} = idx{1};
9199    let Inst{21} = idx{0};
9200  }
9201
9202  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9203                                      V128, V128,
9204                                      V128, VectorIndexS,
9205                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9206    [(set (v2i64 V128:$dst),
9207          (OpNode (v2i64 V128:$Rd),
9208                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9209                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9210    bits<2> idx;
9211    let Inst{11} = idx{1};
9212    let Inst{21} = idx{0};
9213  }
9214  }
9215}
9216
9217//----------------------------------------------------------------------------
9218// AdvSIMD scalar shift by immediate
9219//----------------------------------------------------------------------------
9220
9221let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9222class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9223                     RegisterClass regtype1, RegisterClass regtype2,
9224                     Operand immtype, string asm, list<dag> pattern>
9225  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9226      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9227    Sched<[WriteVd]> {
9228  bits<5> Rd;
9229  bits<5> Rn;
9230  bits<7> imm;
9231  let Inst{31-30} = 0b01;
9232  let Inst{29}    = U;
9233  let Inst{28-23} = 0b111110;
9234  let Inst{22-16} = fixed_imm;
9235  let Inst{15-11} = opc;
9236  let Inst{10}    = 1;
9237  let Inst{9-5} = Rn;
9238  let Inst{4-0} = Rd;
9239}
9240
9241let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9242class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9243                     RegisterClass regtype1, RegisterClass regtype2,
9244                     Operand immtype, string asm, list<dag> pattern>
9245  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9246      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9247    Sched<[WriteVd]> {
9248  bits<5> Rd;
9249  bits<5> Rn;
9250  bits<7> imm;
9251  let Inst{31-30} = 0b01;
9252  let Inst{29}    = U;
9253  let Inst{28-23} = 0b111110;
9254  let Inst{22-16} = fixed_imm;
9255  let Inst{15-11} = opc;
9256  let Inst{10}    = 1;
9257  let Inst{9-5} = Rn;
9258  let Inst{4-0} = Rd;
9259}
9260
9261
9262multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9263  let Predicates = [HasNEON, HasFullFP16] in {
9264  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9265                              FPR16, FPR16, vecshiftR16, asm, []> {
9266    let Inst{19-16} = imm{3-0};
9267  }
9268  } // Predicates = [HasNEON, HasFullFP16]
9269  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9270                              FPR32, FPR32, vecshiftR32, asm, []> {
9271    let Inst{20-16} = imm{4-0};
9272  }
9273  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9274                              FPR64, FPR64, vecshiftR64, asm, []> {
9275    let Inst{21-16} = imm{5-0};
9276  }
9277}
9278
9279multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9280                             SDPatternOperator OpNode> {
9281  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9282                              FPR64, FPR64, vecshiftR64, asm,
9283  [(set (i64 FPR64:$Rd),
9284     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9285    let Inst{21-16} = imm{5-0};
9286  }
9287
9288  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9289            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9290}
9291
9292multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9293                                 SDPatternOperator OpNode = null_frag> {
9294  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9295                              FPR64, FPR64, vecshiftR64, asm,
9296  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9297                                                   (i32 vecshiftR64:$imm)))]> {
9298    let Inst{21-16} = imm{5-0};
9299  }
9300
9301  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9302                           (i32 vecshiftR64:$imm))),
9303            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9304                                            vecshiftR64:$imm)>;
9305}
9306
9307multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9308                             SDPatternOperator OpNode> {
9309  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9310                              FPR64, FPR64, vecshiftL64, asm,
9311    [(set (i64 FPR64:$Rd),
9312       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9313    let Inst{21-16} = imm{5-0};
9314  }
9315
9316  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9317            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9318}
9319
9320let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9321multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9322  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9323                              FPR64, FPR64, vecshiftL64, asm, []> {
9324    let Inst{21-16} = imm{5-0};
9325  }
9326}
9327
9328let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9329multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9330                               SDPatternOperator OpNode = null_frag> {
9331  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9332                              FPR8, FPR16, vecshiftR8, asm, []> {
9333    let Inst{18-16} = imm{2-0};
9334  }
9335
9336  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9337                              FPR16, FPR32, vecshiftR16, asm, []> {
9338    let Inst{19-16} = imm{3-0};
9339  }
9340
9341  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9342                              FPR32, FPR64, vecshiftR32, asm,
9343    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9344    let Inst{20-16} = imm{4-0};
9345  }
9346}
9347
9348multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9349                                SDPatternOperator OpNode> {
9350  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9351                              FPR8, FPR8, vecshiftL8, asm, []> {
9352    let Inst{18-16} = imm{2-0};
9353  }
9354
9355  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9356                              FPR16, FPR16, vecshiftL16, asm, []> {
9357    let Inst{19-16} = imm{3-0};
9358  }
9359
9360  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9361                              FPR32, FPR32, vecshiftL32, asm,
9362    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9363    let Inst{20-16} = imm{4-0};
9364  }
9365
9366  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9367                              FPR64, FPR64, vecshiftL64, asm,
9368    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9369    let Inst{21-16} = imm{5-0};
9370  }
9371
9372  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9373            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9374}
9375
9376multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9377  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9378                              FPR8, FPR8, vecshiftR8, asm, []> {
9379    let Inst{18-16} = imm{2-0};
9380  }
9381
9382  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9383                              FPR16, FPR16, vecshiftR16, asm, []> {
9384    let Inst{19-16} = imm{3-0};
9385  }
9386
9387  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9388                              FPR32, FPR32, vecshiftR32, asm, []> {
9389    let Inst{20-16} = imm{4-0};
9390  }
9391
9392  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9393                              FPR64, FPR64, vecshiftR64, asm, []> {
9394    let Inst{21-16} = imm{5-0};
9395  }
9396}
9397
9398//----------------------------------------------------------------------------
9399// AdvSIMD vector x indexed element
9400//----------------------------------------------------------------------------
9401
9402let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9403class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9404                     RegisterOperand dst_reg, RegisterOperand src_reg,
9405                     Operand immtype,
9406                     string asm, string dst_kind, string src_kind,
9407                     list<dag> pattern>
9408  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9409      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9410           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9411    Sched<[!if(Q, WriteVq, WriteVd)]> {
9412  bits<5> Rd;
9413  bits<5> Rn;
9414  let Inst{31}    = 0;
9415  let Inst{30}    = Q;
9416  let Inst{29}    = U;
9417  let Inst{28-23} = 0b011110;
9418  let Inst{22-16} = fixed_imm;
9419  let Inst{15-11} = opc;
9420  let Inst{10}    = 1;
9421  let Inst{9-5}   = Rn;
9422  let Inst{4-0}   = Rd;
9423}
9424
9425let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9426class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9427                     RegisterOperand vectype1, RegisterOperand vectype2,
9428                     Operand immtype,
9429                     string asm, string dst_kind, string src_kind,
9430                     list<dag> pattern>
9431  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9432      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9433           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9434    Sched<[!if(Q, WriteVq, WriteVd)]> {
9435  bits<5> Rd;
9436  bits<5> Rn;
9437  let Inst{31}    = 0;
9438  let Inst{30}    = Q;
9439  let Inst{29}    = U;
9440  let Inst{28-23} = 0b011110;
9441  let Inst{22-16} = fixed_imm;
9442  let Inst{15-11} = opc;
9443  let Inst{10}    = 1;
9444  let Inst{9-5}   = Rn;
9445  let Inst{4-0}   = Rd;
9446}
9447
9448multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9449                              Intrinsic OpNode> {
9450  let Predicates = [HasNEON, HasFullFP16] in {
9451  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9452                                  V64, V64, vecshiftR16,
9453                                  asm, ".4h", ".4h",
9454      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9455    bits<4> imm;
9456    let Inst{19-16} = imm;
9457  }
9458
9459  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9460                                  V128, V128, vecshiftR16,
9461                                  asm, ".8h", ".8h",
9462      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9463    bits<4> imm;
9464    let Inst{19-16} = imm;
9465  }
9466  } // Predicates = [HasNEON, HasFullFP16]
9467  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9468                                  V64, V64, vecshiftR32,
9469                                  asm, ".2s", ".2s",
9470      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9471    bits<5> imm;
9472    let Inst{20-16} = imm;
9473  }
9474
9475  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9476                                  V128, V128, vecshiftR32,
9477                                  asm, ".4s", ".4s",
9478      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9479    bits<5> imm;
9480    let Inst{20-16} = imm;
9481  }
9482
9483  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9484                                  V128, V128, vecshiftR64,
9485                                  asm, ".2d", ".2d",
9486      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9487    bits<6> imm;
9488    let Inst{21-16} = imm;
9489  }
9490}
9491
9492multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9493                                  Intrinsic OpNode> {
9494  let Predicates = [HasNEON, HasFullFP16] in {
9495  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9496                                  V64, V64, vecshiftR16,
9497                                  asm, ".4h", ".4h",
9498      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9499    bits<4> imm;
9500    let Inst{19-16} = imm;
9501  }
9502
9503  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9504                                  V128, V128, vecshiftR16,
9505                                  asm, ".8h", ".8h",
9506      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9507    bits<4> imm;
9508    let Inst{19-16} = imm;
9509  }
9510  } // Predicates = [HasNEON, HasFullFP16]
9511
9512  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9513                                  V64, V64, vecshiftR32,
9514                                  asm, ".2s", ".2s",
9515      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9516    bits<5> imm;
9517    let Inst{20-16} = imm;
9518  }
9519
9520  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9521                                  V128, V128, vecshiftR32,
9522                                  asm, ".4s", ".4s",
9523      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9524    bits<5> imm;
9525    let Inst{20-16} = imm;
9526  }
9527
9528  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9529                                  V128, V128, vecshiftR64,
9530                                  asm, ".2d", ".2d",
9531      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9532    bits<6> imm;
9533    let Inst{21-16} = imm;
9534  }
9535}
9536
9537multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9538                                     SDPatternOperator OpNode> {
9539  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9540                                  V64, V128, vecshiftR16Narrow,
9541                                  asm, ".8b", ".8h",
9542      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9543    bits<3> imm;
9544    let Inst{18-16} = imm;
9545  }
9546
9547  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9548                                  V128, V128, vecshiftR16Narrow,
9549                                  asm#"2", ".16b", ".8h", []> {
9550    bits<3> imm;
9551    let Inst{18-16} = imm;
9552    let hasSideEffects = 0;
9553  }
9554
9555  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9556                                  V64, V128, vecshiftR32Narrow,
9557                                  asm, ".4h", ".4s",
9558      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9559    bits<4> imm;
9560    let Inst{19-16} = imm;
9561  }
9562
9563  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9564                                  V128, V128, vecshiftR32Narrow,
9565                                  asm#"2", ".8h", ".4s", []> {
9566    bits<4> imm;
9567    let Inst{19-16} = imm;
9568    let hasSideEffects = 0;
9569  }
9570
9571  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9572                                  V64, V128, vecshiftR64Narrow,
9573                                  asm, ".2s", ".2d",
9574      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9575    bits<5> imm;
9576    let Inst{20-16} = imm;
9577  }
9578
9579  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9580                                  V128, V128, vecshiftR64Narrow,
9581                                  asm#"2", ".4s", ".2d", []> {
9582    bits<5> imm;
9583    let Inst{20-16} = imm;
9584    let hasSideEffects = 0;
9585  }
9586
9587  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9588  // themselves, so put them here instead.
9589
9590  // Patterns involving what's effectively an insert high and a normal
9591  // intrinsic, represented by CONCAT_VECTORS.
9592  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9593                                                   vecshiftR16Narrow:$imm)),
9594            (!cast<Instruction>(NAME # "v16i8_shift")
9595                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9596                V128:$Rn, vecshiftR16Narrow:$imm)>;
9597  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9598                                                     vecshiftR32Narrow:$imm)),
9599            (!cast<Instruction>(NAME # "v8i16_shift")
9600                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9601                V128:$Rn, vecshiftR32Narrow:$imm)>;
9602  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9603                                                     vecshiftR64Narrow:$imm)),
9604            (!cast<Instruction>(NAME # "v4i32_shift")
9605                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9606                V128:$Rn, vecshiftR64Narrow:$imm)>;
9607}
9608
9609multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9610                                SDPatternOperator OpNode> {
9611  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9612                                  V64, V64, vecshiftL8,
9613                                  asm, ".8b", ".8b",
9614                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9615                       (i32 vecshiftL8:$imm)))]> {
9616    bits<3> imm;
9617    let Inst{18-16} = imm;
9618  }
9619
9620  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9621                                  V128, V128, vecshiftL8,
9622                                  asm, ".16b", ".16b",
9623             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9624                   (i32 vecshiftL8:$imm)))]> {
9625    bits<3> imm;
9626    let Inst{18-16} = imm;
9627  }
9628
9629  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9630                                  V64, V64, vecshiftL16,
9631                                  asm, ".4h", ".4h",
9632              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9633                    (i32 vecshiftL16:$imm)))]> {
9634    bits<4> imm;
9635    let Inst{19-16} = imm;
9636  }
9637
9638  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9639                                  V128, V128, vecshiftL16,
9640                                  asm, ".8h", ".8h",
9641            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9642                  (i32 vecshiftL16:$imm)))]> {
9643    bits<4> imm;
9644    let Inst{19-16} = imm;
9645  }
9646
9647  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9648                                  V64, V64, vecshiftL32,
9649                                  asm, ".2s", ".2s",
9650              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9651                    (i32 vecshiftL32:$imm)))]> {
9652    bits<5> imm;
9653    let Inst{20-16} = imm;
9654  }
9655
9656  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9657                                  V128, V128, vecshiftL32,
9658                                  asm, ".4s", ".4s",
9659            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9660                  (i32 vecshiftL32:$imm)))]> {
9661    bits<5> imm;
9662    let Inst{20-16} = imm;
9663  }
9664
9665  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9666                                  V128, V128, vecshiftL64,
9667                                  asm, ".2d", ".2d",
9668            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9669                  (i32 vecshiftL64:$imm)))]> {
9670    bits<6> imm;
9671    let Inst{21-16} = imm;
9672  }
9673}
9674
9675multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9676                                SDPatternOperator OpNode> {
9677  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9678                                  V64, V64, vecshiftR8,
9679                                  asm, ".8b", ".8b",
9680                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9681                       (i32 vecshiftR8:$imm)))]> {
9682    bits<3> imm;
9683    let Inst{18-16} = imm;
9684  }
9685
9686  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9687                                  V128, V128, vecshiftR8,
9688                                  asm, ".16b", ".16b",
9689             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9690                   (i32 vecshiftR8:$imm)))]> {
9691    bits<3> imm;
9692    let Inst{18-16} = imm;
9693  }
9694
9695  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9696                                  V64, V64, vecshiftR16,
9697                                  asm, ".4h", ".4h",
9698              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9699                    (i32 vecshiftR16:$imm)))]> {
9700    bits<4> imm;
9701    let Inst{19-16} = imm;
9702  }
9703
9704  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9705                                  V128, V128, vecshiftR16,
9706                                  asm, ".8h", ".8h",
9707            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9708                  (i32 vecshiftR16:$imm)))]> {
9709    bits<4> imm;
9710    let Inst{19-16} = imm;
9711  }
9712
9713  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9714                                  V64, V64, vecshiftR32,
9715                                  asm, ".2s", ".2s",
9716              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9717                    (i32 vecshiftR32:$imm)))]> {
9718    bits<5> imm;
9719    let Inst{20-16} = imm;
9720  }
9721
9722  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9723                                  V128, V128, vecshiftR32,
9724                                  asm, ".4s", ".4s",
9725            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9726                  (i32 vecshiftR32:$imm)))]> {
9727    bits<5> imm;
9728    let Inst{20-16} = imm;
9729  }
9730
9731  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9732                                  V128, V128, vecshiftR64,
9733                                  asm, ".2d", ".2d",
9734            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9735                  (i32 vecshiftR64:$imm)))]> {
9736    bits<6> imm;
9737    let Inst{21-16} = imm;
9738  }
9739}
9740
9741let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9742multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9743                                    SDPatternOperator OpNode = null_frag> {
9744  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9745                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9746                 [(set (v8i8 V64:$dst),
9747                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9748                           (i32 vecshiftR8:$imm)))]> {
9749    bits<3> imm;
9750    let Inst{18-16} = imm;
9751  }
9752
9753  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9754                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9755             [(set (v16i8 V128:$dst),
9756               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9757                       (i32 vecshiftR8:$imm)))]> {
9758    bits<3> imm;
9759    let Inst{18-16} = imm;
9760  }
9761
9762  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9763                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9764              [(set (v4i16 V64:$dst),
9765                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9766                        (i32 vecshiftR16:$imm)))]> {
9767    bits<4> imm;
9768    let Inst{19-16} = imm;
9769  }
9770
9771  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9772                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9773            [(set (v8i16 V128:$dst),
9774              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9775                      (i32 vecshiftR16:$imm)))]> {
9776    bits<4> imm;
9777    let Inst{19-16} = imm;
9778  }
9779
9780  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9781                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9782              [(set (v2i32 V64:$dst),
9783                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9784                        (i32 vecshiftR32:$imm)))]> {
9785    bits<5> imm;
9786    let Inst{20-16} = imm;
9787  }
9788
9789  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9790                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9791            [(set (v4i32 V128:$dst),
9792              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9793                      (i32 vecshiftR32:$imm)))]> {
9794    bits<5> imm;
9795    let Inst{20-16} = imm;
9796  }
9797
9798  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9799                                  V128, V128, vecshiftR64,
9800                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9801              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9802                      (i32 vecshiftR64:$imm)))]> {
9803    bits<6> imm;
9804    let Inst{21-16} = imm;
9805  }
9806}
9807
9808multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9809                                    SDPatternOperator OpNode = null_frag> {
9810  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9811                                  V64, V64, vecshiftL8,
9812                                  asm, ".8b", ".8b",
9813                    [(set (v8i8 V64:$dst),
9814                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9815                                  (i32 vecshiftL8:$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, vecshiftL8,
9822                                  asm, ".16b", ".16b",
9823                    [(set (v16i8 V128:$dst),
9824                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9825                                  (i32 vecshiftL8:$imm)))]> {
9826    bits<3> imm;
9827    let Inst{18-16} = imm;
9828  }
9829
9830  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9831                                  V64, V64, vecshiftL16,
9832                                  asm, ".4h", ".4h",
9833                    [(set (v4i16 V64:$dst),
9834                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9835                                   (i32 vecshiftL16:$imm)))]> {
9836    bits<4> imm;
9837    let Inst{19-16} = imm;
9838  }
9839
9840  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9841                                  V128, V128, vecshiftL16,
9842                                  asm, ".8h", ".8h",
9843                    [(set (v8i16 V128:$dst),
9844                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9845                                  (i32 vecshiftL16:$imm)))]> {
9846    bits<4> imm;
9847    let Inst{19-16} = imm;
9848  }
9849
9850  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9851                                  V64, V64, vecshiftL32,
9852                                  asm, ".2s", ".2s",
9853                    [(set (v2i32 V64:$dst),
9854                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9855                                  (i32 vecshiftL32:$imm)))]> {
9856    bits<5> imm;
9857    let Inst{20-16} = imm;
9858  }
9859
9860  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9861                                  V128, V128, vecshiftL32,
9862                                  asm, ".4s", ".4s",
9863                    [(set (v4i32 V128:$dst),
9864                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9865                                  (i32 vecshiftL32:$imm)))]> {
9866    bits<5> imm;
9867    let Inst{20-16} = imm;
9868  }
9869
9870  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9871                                  V128, V128, vecshiftL64,
9872                                  asm, ".2d", ".2d",
9873                    [(set (v2i64 V128:$dst),
9874                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9875                                  (i32 vecshiftL64:$imm)))]> {
9876    bits<6> imm;
9877    let Inst{21-16} = imm;
9878  }
9879}
9880
9881multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9882                                   SDPatternOperator OpNode> {
9883  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9884                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9885      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9886    bits<3> imm;
9887    let Inst{18-16} = imm;
9888  }
9889
9890  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9891                                  V128, V128, vecshiftL8,
9892                                  asm#"2", ".8h", ".16b",
9893      [(set (v8i16 V128:$Rd),
9894            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
9895    bits<3> imm;
9896    let Inst{18-16} = imm;
9897  }
9898
9899  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9900                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9901      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9902    bits<4> imm;
9903    let Inst{19-16} = imm;
9904  }
9905
9906  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9907                                  V128, V128, vecshiftL16,
9908                                  asm#"2", ".4s", ".8h",
9909      [(set (v4i32 V128:$Rd),
9910            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
9911
9912    bits<4> imm;
9913    let Inst{19-16} = imm;
9914  }
9915
9916  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9917                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9918      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9919    bits<5> imm;
9920    let Inst{20-16} = imm;
9921  }
9922
9923  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9924                                  V128, V128, vecshiftL32,
9925                                  asm#"2", ".2d", ".4s",
9926      [(set (v2i64 V128:$Rd),
9927            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
9928    bits<5> imm;
9929    let Inst{20-16} = imm;
9930  }
9931}
9932
9933
9934//---
9935// Vector load/store
9936//---
9937// SIMD ldX/stX no-index memory references don't allow the optional
9938// ", #0" constant and handle post-indexing explicitly, so we use
9939// a more specialized parse method for them. Otherwise, it's the same as
9940// the general GPR64sp handling.
9941
9942class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9943                   string asm, dag oops, dag iops, list<dag> pattern>
9944  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9945  bits<5> Vt;
9946  bits<5> Rn;
9947  let Inst{31} = 0;
9948  let Inst{30} = Q;
9949  let Inst{29-23} = 0b0011000;
9950  let Inst{22} = L;
9951  let Inst{21-16} = 0b000000;
9952  let Inst{15-12} = opcode;
9953  let Inst{11-10} = size;
9954  let Inst{9-5} = Rn;
9955  let Inst{4-0} = Vt;
9956}
9957
9958class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9959                       string asm, dag oops, dag iops>
9960  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9961  bits<5> Vt;
9962  bits<5> Rn;
9963  bits<5> Xm;
9964  let Inst{31} = 0;
9965  let Inst{30} = Q;
9966  let Inst{29-23} = 0b0011001;
9967  let Inst{22} = L;
9968  let Inst{21} = 0;
9969  let Inst{20-16} = Xm;
9970  let Inst{15-12} = opcode;
9971  let Inst{11-10} = size;
9972  let Inst{9-5} = Rn;
9973  let Inst{4-0} = Vt;
9974}
9975
9976// The immediate form of AdvSIMD post-indexed addressing is encoded with
9977// register post-index addressing from the zero register.
9978multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9979                           int Offset, int Size> {
9980  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9981  //      "ld1\t$Vt, [$Rn], #16"
9982  // may get mapped to
9983  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9984  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9985                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9986                      GPR64sp:$Rn,
9987                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9988                      XZR), 1>;
9989
9990  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9991  //      "ld1.8b\t$Vt, [$Rn], #16"
9992  // may get mapped to
9993  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9994  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9995                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9996                      GPR64sp:$Rn,
9997                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9998                      XZR), 0>;
9999
10000  // E.g. "ld1.8b { v0, v1 }, [x1]"
10001  //      "ld1\t$Vt, [$Rn]"
10002  // may get mapped to
10003  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
10004  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10005                  (!cast<Instruction>(BaseName # Count # "v" # layout)
10006                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10007                      GPR64sp:$Rn), 0>;
10008
10009  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
10010  //      "ld1\t$Vt, [$Rn], $Xm"
10011  // may get mapped to
10012  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
10013  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10014                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10015                      GPR64sp:$Rn,
10016                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10017                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10018}
10019
10020multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
10021                       int Offset128, int Offset64, bits<4> opcode> {
10022  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10023    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
10024                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
10025                           (ins GPR64sp:$Rn), []>;
10026    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
10027                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
10028                           (ins GPR64sp:$Rn), []>;
10029    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
10030                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
10031                           (ins GPR64sp:$Rn), []>;
10032    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
10033                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
10034                           (ins GPR64sp:$Rn), []>;
10035    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
10036                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
10037                           (ins GPR64sp:$Rn), []>;
10038    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
10039                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
10040                           (ins GPR64sp:$Rn), []>;
10041    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
10042                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
10043                           (ins GPR64sp:$Rn), []>;
10044
10045
10046    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
10047                       (outs GPR64sp:$wback,
10048                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
10049                       (ins GPR64sp:$Rn,
10050                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10051    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
10052                       (outs GPR64sp:$wback,
10053                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
10054                       (ins GPR64sp:$Rn,
10055                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10056    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
10057                       (outs GPR64sp:$wback,
10058                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
10059                       (ins GPR64sp:$Rn,
10060                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10061    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
10062                       (outs GPR64sp:$wback,
10063                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
10064                       (ins GPR64sp:$Rn,
10065                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10066    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
10067                       (outs GPR64sp:$wback,
10068                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
10069                       (ins GPR64sp:$Rn,
10070                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10071    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
10072                       (outs GPR64sp:$wback,
10073                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
10074                       (ins GPR64sp:$Rn,
10075                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10076    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
10077                       (outs GPR64sp:$wback,
10078                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
10079                       (ins GPR64sp:$Rn,
10080                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10081  }
10082
10083  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10084  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10085  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10086  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10087  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10088  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10089  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10090}
10091
10092// Only ld1/st1 has a v1d version.
10093multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
10094                       int Offset128, int Offset64, bits<4> opcode> {
10095  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
10096    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
10097                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10098                                 GPR64sp:$Rn), []>;
10099    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
10100                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10101                                GPR64sp:$Rn), []>;
10102    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
10103                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10104                                GPR64sp:$Rn), []>;
10105    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
10106                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10107                                GPR64sp:$Rn), []>;
10108    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
10109                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10110                                GPR64sp:$Rn), []>;
10111    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
10112                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10113                                GPR64sp:$Rn), []>;
10114    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
10115                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10116                                GPR64sp:$Rn), []>;
10117
10118    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
10119                       (outs GPR64sp:$wback),
10120                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10121                            GPR64sp:$Rn,
10122                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10123    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
10124                       (outs GPR64sp:$wback),
10125                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10126                            GPR64sp:$Rn,
10127                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10128    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
10129                       (outs GPR64sp:$wback),
10130                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10131                            GPR64sp:$Rn,
10132                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10133    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
10134                       (outs GPR64sp:$wback),
10135                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10136                            GPR64sp:$Rn,
10137                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10138    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
10139                       (outs GPR64sp:$wback),
10140                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10141                            GPR64sp:$Rn,
10142                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10143    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
10144                       (outs GPR64sp:$wback),
10145                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10146                            GPR64sp:$Rn,
10147                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10148    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
10149                       (outs GPR64sp:$wback),
10150                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10151                            GPR64sp:$Rn,
10152                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10153  }
10154
10155  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10156  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10157  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10158  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10159  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10160  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10161  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10162}
10163
10164multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
10165                       int Offset128, int Offset64, bits<4> opcode>
10166  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10167
10168  // LD1 instructions have extra "1d" variants.
10169  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10170    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
10171                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10172                           (ins GPR64sp:$Rn), []>;
10173
10174    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10175                       (outs GPR64sp:$wback,
10176                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10177                       (ins GPR64sp:$Rn,
10178                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10179  }
10180
10181  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10182}
10183
10184multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10185                       int Offset128, int Offset64, bits<4> opcode>
10186  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10187
10188  // ST1 instructions have extra "1d" variants.
10189  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10190    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10191                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10192                                GPR64sp:$Rn), []>;
10193
10194    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10195                       (outs GPR64sp:$wback),
10196                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10197                            GPR64sp:$Rn,
10198                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10199  }
10200
10201  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10202}
10203
10204multiclass SIMDLd1Multiple<string asm> {
10205  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10206  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10207  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10208  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10209}
10210
10211multiclass SIMDSt1Multiple<string asm> {
10212  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10213  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10214  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10215  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10216}
10217
10218multiclass SIMDLd2Multiple<string asm> {
10219  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10220}
10221
10222multiclass SIMDSt2Multiple<string asm> {
10223  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10224}
10225
10226multiclass SIMDLd3Multiple<string asm> {
10227  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10228}
10229
10230multiclass SIMDSt3Multiple<string asm> {
10231  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10232}
10233
10234multiclass SIMDLd4Multiple<string asm> {
10235  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10236}
10237
10238multiclass SIMDSt4Multiple<string asm> {
10239  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10240}
10241
10242//---
10243// AdvSIMD Load/store single-element
10244//---
10245
10246class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10247                         string asm, string operands, string cst,
10248                         dag oops, dag iops, list<dag> pattern>
10249  : I<oops, iops, asm, operands, cst, pattern> {
10250  bits<5> Vt;
10251  bits<5> Rn;
10252  let Inst{31} = 0;
10253  let Inst{29-24} = 0b001101;
10254  let Inst{22} = L;
10255  let Inst{21} = R;
10256  let Inst{15-13} = opcode;
10257  let Inst{9-5} = Rn;
10258  let Inst{4-0} = Vt;
10259}
10260
10261class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10262                         string asm, string operands, string cst,
10263                         dag oops, dag iops, list<dag> pattern>
10264  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10265  bits<5> Vt;
10266  bits<5> Rn;
10267  let Inst{31} = 0;
10268  let Inst{29-24} = 0b001101;
10269  let Inst{22} = L;
10270  let Inst{21} = R;
10271  let Inst{15-13} = opcode;
10272  let Inst{9-5} = Rn;
10273  let Inst{4-0} = Vt;
10274}
10275
10276
10277let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10278class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10279                  DAGOperand listtype>
10280  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10281                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10282                       []> {
10283  let Inst{30} = Q;
10284  let Inst{23} = 0;
10285  let Inst{20-16} = 0b00000;
10286  let Inst{12} = S;
10287  let Inst{11-10} = size;
10288}
10289let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10290class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10291                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10292  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10293                       "$Rn = $wback",
10294                       (outs GPR64sp:$wback, listtype:$Vt),
10295                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10296  bits<5> Xm;
10297  let Inst{30} = Q;
10298  let Inst{23} = 1;
10299  let Inst{20-16} = Xm;
10300  let Inst{12} = S;
10301  let Inst{11-10} = size;
10302}
10303
10304multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10305                          int Offset, int Size> {
10306  // E.g. "ld1r { v0.8b }, [x1], #1"
10307  //      "ld1r.8b\t$Vt, [$Rn], #1"
10308  // may get mapped to
10309  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10310  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10311                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10312                      GPR64sp:$Rn,
10313                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10314                      XZR), 1>;
10315
10316  // E.g. "ld1r.8b { v0 }, [x1], #1"
10317  //      "ld1r.8b\t$Vt, [$Rn], #1"
10318  // may get mapped to
10319  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10320  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10321                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10322                      GPR64sp:$Rn,
10323                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10324                      XZR), 0>;
10325
10326  // E.g. "ld1r.8b { v0 }, [x1]"
10327  //      "ld1r.8b\t$Vt, [$Rn]"
10328  // may get mapped to
10329  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10330  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10331                  (!cast<Instruction>(BaseName # "v" # layout)
10332                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10333                      GPR64sp:$Rn), 0>;
10334
10335  // E.g. "ld1r.8b { v0 }, [x1], x2"
10336  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10337  // may get mapped to
10338  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10339  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10340                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10341                      GPR64sp:$Rn,
10342                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10343                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10344}
10345
10346multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10347  int Offset1, int Offset2, int Offset4, int Offset8> {
10348  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10349                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10350  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10351                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10352  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10353                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10354  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10355                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10356  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10357                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10358  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10359                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10360  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10361                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10362  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10363                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10364
10365  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10366                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10367                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10368  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10369                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10370                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10371  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10372                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10373                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10374  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10375                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10376                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10377  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10378                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10379                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10380  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10381                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10382                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10383  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10384                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10385                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10386  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10387                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10388                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10389
10390  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10391  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10392  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10393  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10394  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10395  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10396  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10397  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10398}
10399
10400class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10401                      dag oops, dag iops, list<dag> pattern>
10402  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10403                       pattern> {
10404  // idx encoded in Q:S:size fields.
10405  bits<4> idx;
10406  let Inst{30} = idx{3};
10407  let Inst{23} = 0;
10408  let Inst{20-16} = 0b00000;
10409  let Inst{12} = idx{2};
10410  let Inst{11-10} = idx{1-0};
10411}
10412class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10413                      dag oops, dag iops, list<dag> pattern>
10414  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10415                           oops, iops, pattern> {
10416  // idx encoded in Q:S:size fields.
10417  bits<4> idx;
10418  let Inst{30} = idx{3};
10419  let Inst{23} = 0;
10420  let Inst{20-16} = 0b00000;
10421  let Inst{12} = idx{2};
10422  let Inst{11-10} = idx{1-0};
10423}
10424class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10425                          dag oops, dag iops>
10426  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10427                       "$Rn = $wback", oops, iops, []> {
10428  // idx encoded in Q:S:size fields.
10429  bits<4> idx;
10430  bits<5> Xm;
10431  let Inst{30} = idx{3};
10432  let Inst{23} = 1;
10433  let Inst{20-16} = Xm;
10434  let Inst{12} = idx{2};
10435  let Inst{11-10} = idx{1-0};
10436}
10437class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10438                          dag oops, dag iops>
10439  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10440                           "$Rn = $wback", oops, iops, []> {
10441  // idx encoded in Q:S:size fields.
10442  bits<4> idx;
10443  bits<5> Xm;
10444  let Inst{30} = idx{3};
10445  let Inst{23} = 1;
10446  let Inst{20-16} = Xm;
10447  let Inst{12} = idx{2};
10448  let Inst{11-10} = idx{1-0};
10449}
10450
10451class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10452                      dag oops, dag iops, list<dag> pattern>
10453  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10454                       pattern> {
10455  // idx encoded in Q:S:size<1> fields.
10456  bits<3> idx;
10457  let Inst{30} = idx{2};
10458  let Inst{23} = 0;
10459  let Inst{20-16} = 0b00000;
10460  let Inst{12} = idx{1};
10461  let Inst{11} = idx{0};
10462  let Inst{10} = size;
10463}
10464class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10465                      dag oops, dag iops, list<dag> pattern>
10466  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10467                           oops, iops, pattern> {
10468  // idx encoded in Q:S:size<1> fields.
10469  bits<3> idx;
10470  let Inst{30} = idx{2};
10471  let Inst{23} = 0;
10472  let Inst{20-16} = 0b00000;
10473  let Inst{12} = idx{1};
10474  let Inst{11} = idx{0};
10475  let Inst{10} = size;
10476}
10477
10478class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10479                          dag oops, dag iops>
10480  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10481                       "$Rn = $wback", oops, iops, []> {
10482  // idx encoded in Q:S:size<1> fields.
10483  bits<3> idx;
10484  bits<5> Xm;
10485  let Inst{30} = idx{2};
10486  let Inst{23} = 1;
10487  let Inst{20-16} = Xm;
10488  let Inst{12} = idx{1};
10489  let Inst{11} = idx{0};
10490  let Inst{10} = size;
10491}
10492class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10493                          dag oops, dag iops>
10494  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10495                           "$Rn = $wback", oops, iops, []> {
10496  // idx encoded in Q:S:size<1> fields.
10497  bits<3> idx;
10498  bits<5> Xm;
10499  let Inst{30} = idx{2};
10500  let Inst{23} = 1;
10501  let Inst{20-16} = Xm;
10502  let Inst{12} = idx{1};
10503  let Inst{11} = idx{0};
10504  let Inst{10} = size;
10505}
10506class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10507                      dag oops, dag iops, list<dag> pattern>
10508  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10509                       pattern> {
10510  // idx encoded in Q:S fields.
10511  bits<2> idx;
10512  let Inst{30} = idx{1};
10513  let Inst{23} = 0;
10514  let Inst{20-16} = 0b00000;
10515  let Inst{12} = idx{0};
10516  let Inst{11-10} = size;
10517}
10518class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10519                      dag oops, dag iops, list<dag> pattern>
10520  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10521                           oops, iops, pattern> {
10522  // idx encoded in Q:S fields.
10523  bits<2> idx;
10524  let Inst{30} = idx{1};
10525  let Inst{23} = 0;
10526  let Inst{20-16} = 0b00000;
10527  let Inst{12} = idx{0};
10528  let Inst{11-10} = size;
10529}
10530class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10531                          string asm, dag oops, dag iops>
10532  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10533                       "$Rn = $wback", oops, iops, []> {
10534  // idx encoded in Q:S fields.
10535  bits<2> idx;
10536  bits<5> Xm;
10537  let Inst{30} = idx{1};
10538  let Inst{23} = 1;
10539  let Inst{20-16} = Xm;
10540  let Inst{12} = idx{0};
10541  let Inst{11-10} = size;
10542}
10543class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10544                          string asm, dag oops, dag iops>
10545  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10546                           "$Rn = $wback", oops, iops, []> {
10547  // idx encoded in Q:S fields.
10548  bits<2> idx;
10549  bits<5> Xm;
10550  let Inst{30} = idx{1};
10551  let Inst{23} = 1;
10552  let Inst{20-16} = Xm;
10553  let Inst{12} = idx{0};
10554  let Inst{11-10} = size;
10555}
10556class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10557                      dag oops, dag iops, list<dag> pattern>
10558  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10559                       pattern> {
10560  // idx encoded in Q field.
10561  bits<1> idx;
10562  let Inst{30} = idx;
10563  let Inst{23} = 0;
10564  let Inst{20-16} = 0b00000;
10565  let Inst{12} = 0;
10566  let Inst{11-10} = size;
10567}
10568class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10569                      dag oops, dag iops, list<dag> pattern>
10570  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10571                           oops, iops, pattern> {
10572  // idx encoded in Q field.
10573  bits<1> idx;
10574  let Inst{30} = idx;
10575  let Inst{23} = 0;
10576  let Inst{20-16} = 0b00000;
10577  let Inst{12} = 0;
10578  let Inst{11-10} = size;
10579}
10580class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10581                          string asm, dag oops, dag iops>
10582  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10583                       "$Rn = $wback", oops, iops, []> {
10584  // idx encoded in Q field.
10585  bits<1> idx;
10586  bits<5> Xm;
10587  let Inst{30} = idx;
10588  let Inst{23} = 1;
10589  let Inst{20-16} = Xm;
10590  let Inst{12} = 0;
10591  let Inst{11-10} = size;
10592}
10593class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10594                          string asm, dag oops, dag iops>
10595  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10596                           "$Rn = $wback", oops, iops, []> {
10597  // idx encoded in Q field.
10598  bits<1> idx;
10599  bits<5> Xm;
10600  let Inst{30} = idx;
10601  let Inst{23} = 1;
10602  let Inst{20-16} = Xm;
10603  let Inst{12} = 0;
10604  let Inst{11-10} = size;
10605}
10606
10607let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10608multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10609                         RegisterOperand listtype,
10610                         RegisterOperand GPR64pi> {
10611  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10612                           (outs listtype:$dst),
10613                           (ins listtype:$Vt, VectorIndexB:$idx,
10614                                GPR64sp:$Rn), []>;
10615
10616  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10617                            (outs GPR64sp:$wback, listtype:$dst),
10618                            (ins listtype:$Vt, VectorIndexB:$idx,
10619                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10620}
10621let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10622multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10623                         RegisterOperand listtype,
10624                         RegisterOperand GPR64pi> {
10625  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10626                            (outs listtype:$dst),
10627                            (ins listtype:$Vt, VectorIndexH:$idx,
10628                                 GPR64sp:$Rn), []>;
10629
10630  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10631                            (outs GPR64sp:$wback, listtype:$dst),
10632                            (ins listtype:$Vt, VectorIndexH:$idx,
10633                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10634}
10635let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10636multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10637                         RegisterOperand listtype,
10638                         RegisterOperand GPR64pi> {
10639  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10640                            (outs listtype:$dst),
10641                            (ins listtype:$Vt, VectorIndexS:$idx,
10642                                 GPR64sp:$Rn), []>;
10643
10644  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10645                            (outs GPR64sp:$wback, listtype:$dst),
10646                            (ins listtype:$Vt, VectorIndexS:$idx,
10647                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10648}
10649let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10650multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10651                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10652  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10653                            (outs listtype:$dst),
10654                            (ins listtype:$Vt, VectorIndexD:$idx,
10655                                 GPR64sp:$Rn), []>;
10656
10657  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10658                            (outs GPR64sp:$wback, listtype:$dst),
10659                            (ins listtype:$Vt, VectorIndexD:$idx,
10660                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10661}
10662let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10663multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10664                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10665  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10666                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10667                                        GPR64sp:$Rn), []>;
10668
10669  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10670                                    (outs GPR64sp:$wback),
10671                                    (ins listtype:$Vt, VectorIndexB:$idx,
10672                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10673}
10674let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10675multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10676                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10677  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10678                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10679                                         GPR64sp:$Rn), []>;
10680
10681  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10682                            (outs GPR64sp:$wback),
10683                            (ins listtype:$Vt, VectorIndexH:$idx,
10684                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10685}
10686let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10687multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10688                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10689  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10690                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10691                                         GPR64sp:$Rn), []>;
10692
10693  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10694                            (outs GPR64sp:$wback),
10695                            (ins listtype:$Vt, VectorIndexS:$idx,
10696                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10697}
10698let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10699multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10700                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10701  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10702                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10703                                         GPR64sp:$Rn), []>;
10704
10705  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10706                            (outs GPR64sp:$wback),
10707                            (ins listtype:$Vt, VectorIndexD:$idx,
10708                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10709}
10710
10711multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10712                                 string Count, int Offset, Operand idxtype> {
10713  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10714  //      "ld1\t$Vt, [$Rn], #1"
10715  // may get mapped to
10716  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10717  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10718                  (!cast<Instruction>(NAME # Type  # "_POST")
10719                      GPR64sp:$Rn,
10720                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10721                      idxtype:$idx, XZR), 1>;
10722
10723  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10724  //      "ld1.8b\t$Vt, [$Rn], #1"
10725  // may get mapped to
10726  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10727  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10728                  (!cast<Instruction>(NAME # Type # "_POST")
10729                      GPR64sp:$Rn,
10730                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10731                      idxtype:$idx, XZR), 0>;
10732
10733  // E.g. "ld1.8b { v0 }[0], [x1]"
10734  //      "ld1.8b\t$Vt, [$Rn]"
10735  // may get mapped to
10736  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10737  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10738                      (!cast<Instruction>(NAME # Type)
10739                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10740                         idxtype:$idx, GPR64sp:$Rn), 0>;
10741
10742  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10743  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10744  // may get mapped to
10745  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10746  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10747                      (!cast<Instruction>(NAME # Type # "_POST")
10748                         GPR64sp:$Rn,
10749                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10750                         idxtype:$idx,
10751                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10752}
10753
10754multiclass SIMDLdSt1SingleAliases<string asm> {
10755  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10756  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10757  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10758  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10759}
10760
10761multiclass SIMDLdSt2SingleAliases<string asm> {
10762  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10763  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10764  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10765  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10766}
10767
10768multiclass SIMDLdSt3SingleAliases<string asm> {
10769  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10770  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10771  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10772  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10773}
10774
10775multiclass SIMDLdSt4SingleAliases<string asm> {
10776  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10777  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10778  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10779  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10780}
10781} // end of 'let Predicates = [HasNEON]'
10782
10783//----------------------------------------------------------------------------
10784// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10785//----------------------------------------------------------------------------
10786
10787let Predicates = [HasNEON, HasRDM] in {
10788
10789class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10790                                    RegisterOperand regtype, string asm,
10791                                    string kind, list<dag> pattern>
10792  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10793                                pattern> {
10794}
10795multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10796                                             SDPatternOperator op> {
10797  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10798    [(set (v4i16 V64:$dst),
10799          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
10800  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10801    [(set (v8i16 V128:$dst),
10802          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
10803  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10804    [(set (v2i32 V64:$dst),
10805          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
10806  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10807    [(set (v4i32 V128:$dst),
10808          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
10809}
10810
10811multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10812                                     SDPatternOperator op> {
10813  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10814                                          V64, V64, V128_lo, VectorIndexH,
10815                                          asm, ".4h", ".4h", ".4h", ".h",
10816    [(set (v4i16 V64:$dst),
10817          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10818                     (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10819                                              VectorIndexH:$idx)))))]> {
10820    bits<3> idx;
10821    let Inst{11} = idx{2};
10822    let Inst{21} = idx{1};
10823    let Inst{20} = idx{0};
10824  }
10825
10826  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10827                                          V128, V128, V128_lo, VectorIndexH,
10828                                          asm, ".8h", ".8h", ".8h", ".h",
10829    [(set (v8i16 V128:$dst),
10830          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10831                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10832                                              VectorIndexH:$idx)))))]> {
10833    bits<3> idx;
10834    let Inst{11} = idx{2};
10835    let Inst{21} = idx{1};
10836    let Inst{20} = idx{0};
10837  }
10838
10839  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10840                                          V64, V64, V128, VectorIndexS,
10841                                          asm, ".2s", ".2s", ".2s", ".s",
10842    [(set (v2i32 V64:$dst),
10843          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10844                     (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10845                                              VectorIndexS:$idx)))))]> {
10846    bits<2> idx;
10847    let Inst{11} = idx{1};
10848    let Inst{21} = idx{0};
10849  }
10850
10851  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10852                                          V128, V128, V128, VectorIndexS,
10853                                          asm, ".4s", ".4s", ".4s", ".s",
10854    [(set (v4i32 V128:$dst),
10855          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10856                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10857                                              VectorIndexS:$idx)))))]> {
10858    bits<2> idx;
10859    let Inst{11} = idx{1};
10860    let Inst{21} = idx{0};
10861  }
10862
10863  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10864                                        FPR16Op, FPR16Op, V128_lo,
10865                                        VectorIndexH, asm, ".h", "", "", ".h",
10866                                        []> {
10867    bits<3> idx;
10868    let Inst{11} = idx{2};
10869    let Inst{21} = idx{1};
10870    let Inst{20} = idx{0};
10871  }
10872
10873  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10874                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10875                                        asm, ".s", "", "", ".s",
10876    [(set (i32 FPR32Op:$dst),
10877          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
10878                   (i32 (vector_extract (v4i32 V128:$Rm),
10879                                        VectorIndexS:$idx)))))]> {
10880    bits<2> idx;
10881    let Inst{11} = idx{1};
10882    let Inst{21} = idx{0};
10883  }
10884}
10885} // let Predicates = [HasNeon, HasRDM]
10886
10887//----------------------------------------------------------------------------
10888// ARMv8.3 Complex ADD/MLA instructions
10889//----------------------------------------------------------------------------
10890
10891class ComplexRotationOperand<int Angle, int Remainder, string Type>
10892  : AsmOperandClass {
10893  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10894  let DiagnosticType = "InvalidComplexRotation" # Type;
10895  let Name = "ComplexRotation" # Type;
10896}
10897def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10898                                                  SDNodeXForm<imm, [{
10899  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10900}]>> {
10901  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10902  let PrintMethod = "printComplexRotationOp<90, 0>";
10903}
10904def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10905                                                  SDNodeXForm<imm, [{
10906  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10907}]>> {
10908  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10909  let PrintMethod = "printComplexRotationOp<180, 90>";
10910}
10911let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
10912class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10913                                     RegisterOperand regtype, Operand rottype,
10914                                     string asm, string kind, list<dag> pattern>
10915  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10916      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10917      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10918    Sched<[!if(Q, WriteVq, WriteVd)]> {
10919  bits<5> Rd;
10920  bits<5> Rn;
10921  bits<5> Rm;
10922  bits<1> rot;
10923  let Inst{31}    = 0;
10924  let Inst{30}    = Q;
10925  let Inst{29}    = U;
10926  let Inst{28-24} = 0b01110;
10927  let Inst{23-22} = size;
10928  let Inst{21}    = 0;
10929  let Inst{20-16} = Rm;
10930  let Inst{15-13} = opcode;
10931  // Non-tied version (FCADD) only has one rotation bit
10932  let Inst{12}    = rot;
10933  let Inst{11}    = 0;
10934  let Inst{10}    = 1;
10935  let Inst{9-5}   = Rn;
10936  let Inst{4-0}   = Rd;
10937}
10938
10939//8.3 CompNum - Floating-point complex number support
10940multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10941                                          string asm, SDPatternOperator OpNode>{
10942  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10943  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10944              asm, ".4h",
10945              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10946                                              (v4f16 V64:$Rn),
10947                                              (v4f16 V64:$Rm),
10948                                              (i32 rottype:$rot)))]>;
10949
10950  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10951              asm, ".8h",
10952              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10953                                               (v8f16 V128:$Rn),
10954                                               (v8f16 V128:$Rm),
10955                                               (i32 rottype:$rot)))]>;
10956  }
10957
10958  let Predicates = [HasComplxNum, HasNEON] in {
10959  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10960              asm, ".2s",
10961              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10962                                              (v2f32 V64:$Rn),
10963                                              (v2f32 V64:$Rm),
10964                                              (i32 rottype:$rot)))]>;
10965
10966  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10967              asm, ".4s",
10968              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10969                                               (v4f32 V128:$Rn),
10970                                               (v4f32 V128:$Rm),
10971                                               (i32 rottype:$rot)))]>;
10972
10973  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10974              asm, ".2d",
10975              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10976                                               (v2f64 V128:$Rn),
10977                                               (v2f64 V128:$Rm),
10978                                               (i32 rottype:$rot)))]>;
10979  }
10980}
10981
10982let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
10983class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10984                                         bits<3> opcode,
10985                                         RegisterOperand regtype,
10986                                         Operand rottype, string asm,
10987                                         string kind, list<dag> pattern>
10988  : I<(outs regtype:$dst),
10989      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10990      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10991      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10992    Sched<[!if(Q, WriteVq, WriteVd)]> {
10993  bits<5> Rd;
10994  bits<5> Rn;
10995  bits<5> Rm;
10996  bits<2> rot;
10997  let Inst{31}    = 0;
10998  let Inst{30}    = Q;
10999  let Inst{29}    = U;
11000  let Inst{28-24} = 0b01110;
11001  let Inst{23-22} = size;
11002  let Inst{21}    = 0;
11003  let Inst{20-16} = Rm;
11004  let Inst{15-13} = opcode;
11005  let Inst{12-11} = rot;
11006  let Inst{10}    = 1;
11007  let Inst{9-5}   = Rn;
11008  let Inst{4-0}   = Rd;
11009}
11010
11011multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
11012                                             Operand rottype, string asm,
11013                                             SDPatternOperator OpNode> {
11014  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11015  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
11016              rottype, asm, ".4h",
11017              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11018                                              (v4f16 V64:$Rn),
11019                                              (v4f16 V64:$Rm),
11020                                              (i32 rottype:$rot)))]>;
11021
11022  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
11023              rottype, asm, ".8h",
11024              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11025                                               (v8f16 V128:$Rn),
11026                                               (v8f16 V128:$Rm),
11027                                               (i32 rottype:$rot)))]>;
11028  }
11029
11030  let Predicates = [HasComplxNum, HasNEON] in {
11031  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
11032              rottype, asm, ".2s",
11033              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11034                                              (v2f32 V64:$Rn),
11035                                              (v2f32 V64:$Rm),
11036                                              (i32 rottype:$rot)))]>;
11037
11038  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
11039              rottype, asm, ".4s",
11040              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11041                                               (v4f32 V128:$Rn),
11042                                               (v4f32 V128:$Rm),
11043                                               (i32 rottype:$rot)))]>;
11044
11045  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
11046              rottype, asm, ".2d",
11047              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11048                                               (v2f64 V128:$Rn),
11049                                               (v2f64 V128:$Rm),
11050                                               (i32 rottype:$rot)))]>;
11051  }
11052}
11053
11054let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11055class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
11056                                 bit opc1, bit opc2, RegisterOperand dst_reg,
11057                                 RegisterOperand lhs_reg,
11058                                 RegisterOperand rhs_reg, Operand vec_idx,
11059                                 Operand rottype, string asm, string apple_kind,
11060                                 string dst_kind, string lhs_kind,
11061                                 string rhs_kind, list<dag> pattern>
11062  : I<(outs dst_reg:$dst),
11063      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
11064      asm,
11065      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
11066      "$idx, $rot" # "|" # apple_kind #
11067      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
11068    Sched<[!if(Q, WriteVq, WriteVd)]> {
11069  bits<5> Rd;
11070  bits<5> Rn;
11071  bits<5> Rm;
11072  bits<2> rot;
11073
11074  let Inst{31}    = 0;
11075  let Inst{30}    = Q;
11076  let Inst{29}    = U;
11077  let Inst{28}    = Scalar;
11078  let Inst{27-24} = 0b1111;
11079  let Inst{23-22} = size;
11080  // Bit 21 must be set by the derived class.
11081  let Inst{20-16} = Rm;
11082  let Inst{15}    = opc1;
11083  let Inst{14-13} = rot;
11084  let Inst{12}    = opc2;
11085  // Bit 11 must be set by the derived class.
11086  let Inst{10}    = 0;
11087  let Inst{9-5}   = Rn;
11088  let Inst{4-0}   = Rd;
11089}
11090
11091// The complex instructions index by pairs of elements, so the VectorIndexes
11092// don't match the lane types, and the index bits are different to the other
11093// classes.
11094multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
11095                                     string asm> {
11096  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11097  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
11098                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
11099                      ".4h", ".h", []> {
11100    bits<1> idx;
11101    let Inst{11} = 0;
11102    let Inst{21} = idx{0};
11103  }
11104
11105  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
11106                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
11107                      ".8h", ".8h", ".h", []> {
11108    bits<2> idx;
11109    let Inst{11} = idx{1};
11110    let Inst{21} = idx{0};
11111  }
11112  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
11113
11114  let Predicates = [HasComplxNum, HasNEON] in {
11115  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
11116                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
11117                      ".4s", ".4s", ".s", []> {
11118    bits<1> idx;
11119    let Inst{11} = idx{0};
11120    let Inst{21} = 0;
11121  }
11122  } // Predicates = [HasComplxNum, HasNEON]
11123}
11124
11125//----------------------------------------------------------------------------
11126// Crypto extensions
11127//----------------------------------------------------------------------------
11128
11129let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11130class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
11131              list<dag> pat>
11132  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
11133    Sched<[WriteVq]>{
11134  bits<5> Rd;
11135  bits<5> Rn;
11136  let Inst{31-16} = 0b0100111000101000;
11137  let Inst{15-12} = opc;
11138  let Inst{11-10} = 0b10;
11139  let Inst{9-5}   = Rn;
11140  let Inst{4-0}   = Rd;
11141}
11142
11143class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
11144  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
11145            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
11146
11147class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
11148  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
11149            "$Rd = $dst",
11150            [(set (v16i8 V128:$dst),
11151                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
11152
11153let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11154class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
11155                     dag oops, dag iops, list<dag> pat>
11156  : I<oops, iops, asm,
11157      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
11158      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
11159    Sched<[WriteVq]>{
11160  bits<5> Rd;
11161  bits<5> Rn;
11162  bits<5> Rm;
11163  let Inst{31-21} = 0b01011110000;
11164  let Inst{20-16} = Rm;
11165  let Inst{15}    = 0;
11166  let Inst{14-12} = opc;
11167  let Inst{11-10} = 0b00;
11168  let Inst{9-5}   = Rn;
11169  let Inst{4-0}   = Rd;
11170}
11171
11172class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11173  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11174                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11175                   [(set (v4i32 FPR128:$dst),
11176                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11177                                 (v4i32 V128:$Rm)))]>;
11178
11179class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11180  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11181                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11182                   [(set (v4i32 V128:$dst),
11183                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11184                                 (v4i32 V128:$Rm)))]>;
11185
11186class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11187  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11188                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11189                   [(set (v4i32 FPR128:$dst),
11190                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11191                                 (v4i32 V128:$Rm)))]>;
11192
11193let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11194class SHA2OpInst<bits<4> opc, string asm, string kind,
11195                 string cstr, dag oops, dag iops,
11196                 list<dag> pat>
11197  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11198                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11199    Sched<[WriteVq]>{
11200  bits<5> Rd;
11201  bits<5> Rn;
11202  let Inst{31-16} = 0b0101111000101000;
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 SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11210  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11211               (ins V128:$Rd, V128:$Rn),
11212               [(set (v4i32 V128:$dst),
11213                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11214
11215class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11216  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11217               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11218
11219// Armv8.2-A Crypto extensions
11220class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11221                    list<dag> pattern>
11222  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11223  bits<5> Vd;
11224  bits<5> Vn;
11225  let Inst{31-25} = 0b1100111;
11226  let Inst{9-5}   = Vn;
11227  let Inst{4-0}   = Vd;
11228}
11229
11230class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11231  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11232                  "$Vd = $Vdst", []> {
11233  let Inst{31-25} = 0b1100111;
11234  let Inst{24-21} = 0b0110;
11235  let Inst{20-15} = 0b000001;
11236  let Inst{14}    = op0;
11237  let Inst{13-12} = 0b00;
11238  let Inst{11-10} = op1;
11239}
11240class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11241  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11242class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11243  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11244
11245class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11246                string asmops, string cst>
11247  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11248  bits<5> Vm;
11249  let Inst{24-21} = 0b0011;
11250  let Inst{20-16} = Vm;
11251  let Inst{15}    = 0b1;
11252  let Inst{14}    = op0;
11253  let Inst{13-12} = 0b00;
11254  let Inst{11-10} = op1;
11255}
11256class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11257  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11258              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11259class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11260  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11261              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11262class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11263  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11264              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11265class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11266  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11267              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11268class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11269  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11270              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11271
11272class CryptoRRRR<bits<2>op0, string asm, string asmops>
11273  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11274                  asmops, "", []> {
11275  bits<5> Vm;
11276  bits<5> Va;
11277  let Inst{24-23} = 0b00;
11278  let Inst{22-21} = op0;
11279  let Inst{20-16} = Vm;
11280  let Inst{15}    = 0b0;
11281  let Inst{14-10} = Va;
11282}
11283class CryptoRRRR_16B<bits<2>op0, string asm>
11284 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11285                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11286}
11287class CryptoRRRR_4S<bits<2>op0, string asm>
11288 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11289                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11290}
11291
11292class CryptoRRRi6<string asm>
11293  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11294                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11295                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11296  bits<6> imm;
11297  bits<5> Vm;
11298  let Inst{24-21} = 0b0100;
11299  let Inst{20-16} = Vm;
11300  let Inst{15-10} = imm;
11301  let Inst{9-5}   = Vn;
11302  let Inst{4-0}   = Vd;
11303}
11304
11305class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11306  : BaseCryptoV82<(outs V128:$Vdst),
11307                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11308                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11309                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11310  bits<2> imm;
11311  bits<5> Vm;
11312  let Inst{24-21} = 0b0010;
11313  let Inst{20-16} = Vm;
11314  let Inst{15}    = 0b1;
11315  let Inst{14}    = op0;
11316  let Inst{13-12} = imm;
11317  let Inst{11-10} = op1;
11318}
11319
11320//----------------------------------------------------------------------------
11321// v8.1 atomic instructions extension:
11322// * CAS
11323// * CASP
11324// * SWP
11325// * LDOPregister<OP>, and aliases STOPregister<OP>
11326
11327// Instruction encodings:
11328//
11329//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11330// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11331// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11332// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11333// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11334// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11335
11336// Instruction syntax:
11337//
11338// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11339// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11340// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11341// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11342// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11343// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11344// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11345// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11346// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11347// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11348
11349let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11350class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11351                      string cstr, list<dag> pattern>
11352      : I<oops, iops, asm, operands, cstr, pattern> {
11353  bits<2> Sz;
11354  bit NP;
11355  bit Acq;
11356  bit Rel;
11357  bits<5> Rs;
11358  bits<5> Rn;
11359  bits<5> Rt;
11360  let Inst{31-30} = Sz;
11361  let Inst{29-24} = 0b001000;
11362  let Inst{23} = NP;
11363  let Inst{22} = Acq;
11364  let Inst{21} = 0b1;
11365  let Inst{20-16} = Rs;
11366  let Inst{15} = Rel;
11367  let Inst{14-10} = 0b11111;
11368  let Inst{9-5} = Rn;
11369  let Inst{4-0} = Rt;
11370  let Predicates = [HasLSE];
11371}
11372
11373class BaseCAS<string order, string size, RegisterClass RC>
11374      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11375                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11376                        "$out = $Rs",[]>,
11377        Sched<[WriteAtomic]> {
11378  let NP = 1;
11379}
11380
11381multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11382  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11383  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11384  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11385  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11386}
11387
11388class BaseCASP<string order, string size, RegisterOperand RC>
11389      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11390                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11391                        "$out = $Rs",[]>,
11392        Sched<[WriteAtomic]> {
11393  let NP = 0;
11394}
11395
11396multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11397  let Sz = 0b00, Acq = Acq, Rel = Rel in
11398    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11399  let Sz = 0b01, Acq = Acq, Rel = Rel in
11400    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11401}
11402
11403let Predicates = [HasLSE] in
11404class BaseSWP<string order, string size, RegisterClass RC>
11405      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11406          "\t$Rs, $Rt, [$Rn]","",[]>,
11407        Sched<[WriteAtomic]> {
11408  bits<2> Sz;
11409  bit Acq;
11410  bit Rel;
11411  bits<5> Rs;
11412  bits<3> opc = 0b000;
11413  bits<5> Rn;
11414  bits<5> Rt;
11415  let Inst{31-30} = Sz;
11416  let Inst{29-24} = 0b111000;
11417  let Inst{23} = Acq;
11418  let Inst{22} = Rel;
11419  let Inst{21} = 0b1;
11420  let Inst{20-16} = Rs;
11421  let Inst{15} = 0b1;
11422  let Inst{14-12} = opc;
11423  let Inst{11-10} = 0b00;
11424  let Inst{9-5} = Rn;
11425  let Inst{4-0} = Rt;
11426  let Predicates = [HasLSE];
11427}
11428
11429multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11430  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11431  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11432  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11433  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11434}
11435
11436let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11437class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11438      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11439          "\t$Rs, $Rt, [$Rn]","",[]>,
11440        Sched<[WriteAtomic]> {
11441  bits<2> Sz;
11442  bit Acq;
11443  bit Rel;
11444  bits<5> Rs;
11445  bits<3> opc;
11446  bits<5> Rn;
11447  bits<5> Rt;
11448  let Inst{31-30} = Sz;
11449  let Inst{29-24} = 0b111000;
11450  let Inst{23} = Acq;
11451  let Inst{22} = Rel;
11452  let Inst{21} = 0b1;
11453  let Inst{20-16} = Rs;
11454  let Inst{15} = 0b0;
11455  let Inst{14-12} = opc;
11456  let Inst{11-10} = 0b00;
11457  let Inst{9-5} = Rn;
11458  let Inst{4-0} = Rt;
11459  let Predicates = [HasLSE];
11460}
11461
11462multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11463                        string order> {
11464  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11465    def B : BaseLDOPregister<op, order, "b", GPR32>;
11466  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11467    def H : BaseLDOPregister<op, order, "h", GPR32>;
11468  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11469    def W : BaseLDOPregister<op, order, "", GPR32>;
11470  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11471    def X : BaseLDOPregister<op, order, "", GPR64>;
11472}
11473
11474// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11475// complex DAG for DstRHS.
11476let Predicates = [HasLSE] in
11477multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11478                                         string size, dag SrcRHS, dag DstRHS> {
11479  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11480            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11481  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11482            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11483  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11484            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11485  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11486            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11487  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11488            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11489}
11490
11491multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11492                                     string size, dag RHS> {
11493  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11494}
11495
11496multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11497                                         string size, dag LHS, dag RHS> {
11498  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11499}
11500
11501multiclass LDOPregister_patterns<string inst, string op> {
11502  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11503  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11504  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11505  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11506}
11507
11508multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11509  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11510                        (i64 GPR64:$Rm),
11511                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11512  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11513                        (i32 GPR32:$Rm),
11514                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11515  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11516                        (i32 GPR32:$Rm),
11517                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11518  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11519                        (i32 GPR32:$Rm),
11520                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11521}
11522
11523let Predicates = [HasLSE] in
11524multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11525                                        string size, dag OLD, dag NEW> {
11526  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11527            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11528  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11529            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11530  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11531            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11532  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11533            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11534  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11535            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11536}
11537
11538multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11539                                    string size, dag OLD, dag NEW> {
11540  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11541}
11542
11543multiclass CASregister_patterns<string inst, string op> {
11544  defm : CASregister_patterns_ord<inst, "X", op, "64",
11545                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11546  defm : CASregister_patterns_ord<inst, "W", op, "32",
11547                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11548  defm : CASregister_patterns_ord<inst, "H", op, "16",
11549                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11550  defm : CASregister_patterns_ord<inst, "B", op, "8",
11551                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11552}
11553
11554let Predicates = [HasLSE] in
11555class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11556                        Instruction inst> :
11557      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11558
11559multiclass STOPregister<string asm, string instr> {
11560  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11561                    !cast<Instruction>(instr # "LB")>;
11562  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11563                    !cast<Instruction>(instr # "LH")>;
11564  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11565                    !cast<Instruction>(instr # "LW")>;
11566  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11567                    !cast<Instruction>(instr # "LX")>;
11568  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11569                    !cast<Instruction>(instr # "B")>;
11570  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11571                    !cast<Instruction>(instr # "H")>;
11572  def : BaseSTOPregister<asm,        GPR32, WZR,
11573                    !cast<Instruction>(instr # "W")>;
11574  def : BaseSTOPregister<asm,        GPR64, XZR,
11575                    !cast<Instruction>(instr # "X")>;
11576}
11577
11578class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11579                        dag iops, dag oops, list<dag> pat>
11580    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11581      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11582  bits<5> Rt;
11583  bits<5> Rn;
11584  let Inst{31-21} = 0b11111000001;
11585  let Inst{15}    = 1;
11586  let Inst{14-12} = opc;
11587  let Inst{11-10} = 0b00;
11588  let Inst{9-5}   = Rn;
11589  let Inst{4-0}   = Rt;
11590
11591  let Predicates = [HasV8_7a];
11592}
11593
11594class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11595                      list<dag> pat = []>
11596    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11597  let Inst{20-16} = 0b11111;
11598}
11599
11600class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11601    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11602                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11603  bits<5> Rs;
11604  let Inst{20-16} = Rs;
11605}
11606
11607class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11608                             bits<2> op2, string asm>
11609  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11610      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11611      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11612      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11613    Sched<[]> {
11614  bits<5> Rd;
11615  bits<5> Rs;
11616  bits<5> Rn;
11617  let Inst{31-27} = 0b00011;
11618  let Inst{26} = isMove;
11619  let Inst{25-24} = 0b01;
11620  let Inst{23-22} = opcode;
11621  let Inst{21} = 0b0;
11622  let Inst{20-16} = Rs;
11623  let Inst{15-14} = op2;
11624  let Inst{13-12} = op1;
11625  let Inst{11-10} = 0b01;
11626  let Inst{9-5} = Rn;
11627  let Inst{4-0} = Rd;
11628
11629  let DecoderMethod = "DecodeCPYMemOpInstruction";
11630  let mayLoad = 1;
11631  let mayStore = 1;
11632}
11633
11634class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11635  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11636
11637class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11638  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11639
11640class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11641                        string asm>
11642  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11643      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11644      asm, "\t[$Rd]!, $Rn!, $Rm",
11645      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11646    Sched<[]> {
11647  bits<5> Rd;
11648  bits<5> Rn;
11649  bits<5> Rm;
11650  let Inst{31-27} = 0b00011;
11651  let Inst{26} = isTagging;
11652  let Inst{25-21} = 0b01110;
11653  let Inst{20-16} = Rm;
11654  let Inst{15-14} = opcode;
11655  let Inst{13} = op2;
11656  let Inst{12} = op1;
11657  let Inst{11-10} = 0b01;
11658  let Inst{9-5} = Rn;
11659  let Inst{4-0} = Rd;
11660
11661  let DecoderMethod = "DecodeSETMemOpInstruction";
11662  let mayLoad = 0;
11663  let mayStore = 1;
11664}
11665
11666class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
11667  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
11668
11669class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
11670  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
11671
11672multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
11673  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
11674  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
11675  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
11676  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
11677  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
11678  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
11679  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
11680  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
11681  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
11682  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
11683  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
11684  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
11685  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
11686  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
11687  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
11688  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
11689}
11690
11691multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
11692  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
11693  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
11694  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
11695  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
11696  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
11697  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
11698  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
11699  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
11700  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
11701  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
11702  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
11703  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
11704  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
11705  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
11706  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
11707  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
11708}
11709
11710multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
11711  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
11712  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
11713  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
11714  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
11715}
11716
11717multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
11718  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
11719  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
11720  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
11721  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
11722}
11723
11724//----------------------------------------------------------------------------
11725// 2022 Armv8.9/Armv9.4 Extensions
11726//----------------------------------------------------------------------------
11727
11728//---
11729// 2022 Architecture Extensions: General Data Processing (FEAT_CSSC)
11730//---
11731
11732class BaseTwoOperandRegImm<bit sf, bit Op, bit S, bits<4> opc,
11733                           RegisterClass regtype, ImmLeaf immtype, string asm,
11734                           SDPatternOperator OpNode>
11735    : I<(outs regtype:$Rd), (ins regtype:$Rn, immtype:$imm),
11736        asm, "\t$Rd, $Rn, $imm", "",
11737        [(set regtype:$Rd, (OpNode regtype:$Rn, immtype:$imm))]> {
11738  bits<5> Rd;
11739  bits<5> Rn;
11740  bits<8> imm;
11741
11742  let Inst{31}    = sf;
11743  let Inst{30}    = Op;
11744  let Inst{29}    = S;
11745  let Inst{28-22} = 0b1000111;
11746  let Inst{21-18} = opc;
11747  let Inst{17-10} = imm;
11748  let Inst{9-5}   = Rn;
11749  let Inst{4-0}   = Rd;
11750}
11751
11752class BaseComparisonOpReg<bit size, bit isUnsigned, bit isMin,
11753                          RegisterClass regtype, string asm,
11754                          SDPatternOperator OpNode>
11755    : BaseTwoOperandRegReg<size, 0b0, {0,1,1,0,?,?}, regtype, asm, OpNode>,
11756      Sched<[WriteI]> {
11757  let Inst{11} = isMin;
11758  let Inst{10} = isUnsigned;
11759  let mayLoad  = 0;
11760  let mayStore = 0;
11761  let hasSideEffects = 0;
11762}
11763
11764class BaseComparisonOpImm<bit size, bit isUnsigned, bit isMin,
11765                          RegisterClass regtype, ImmLeaf immtype, string asm,
11766                          SDPatternOperator OpNode>
11767    : BaseTwoOperandRegImm<size, 0b0, 0b0, {0,0,?,?}, regtype, immtype, asm,
11768                           OpNode>,
11769      Sched<[]> {
11770  let Inst{19} = isMin;
11771  let Inst{18} = isUnsigned;
11772  let mayLoad  = 0;
11773  let mayStore = 0;
11774  let hasSideEffects = 0;
11775}
11776
11777multiclass ComparisonOp<bit isUnsigned, bit isMin, string asm,
11778                        SDPatternOperator OpNode = null_frag> {
11779  def Wrr : BaseComparisonOpReg<0b0, isUnsigned, isMin, GPR32, asm, OpNode>;
11780
11781  def Wri : BaseComparisonOpImm<0b0, isUnsigned, isMin, GPR32,
11782                                !cond(isUnsigned : uimm8_32b,
11783                                      !not(isUnsigned) : simm8_32b), asm, OpNode>;
11784
11785  def Xrr : BaseComparisonOpReg<0b1, isUnsigned, isMin, GPR64, asm, OpNode>;
11786
11787  def Xri : BaseComparisonOpImm<0b1, isUnsigned, isMin, GPR64,
11788                                !cond(isUnsigned : uimm8_64b,
11789                                      !not(isUnsigned) : simm8_64b), asm, OpNode>;
11790}
11791
11792//---
11793// RCPC instructions (FEAT_LRCPC3)
11794//---
11795
11796class BaseLRCPC3<bits<2> size, bit V, bits<2> opc, dag oops, dag iops,
11797                 string asm, string operands, string cstr = "">
11798      : I<oops, iops, asm, operands, cstr, []>,
11799        Sched<[WriteAtomic]> {
11800  bits<5> Rt;
11801  bits<5> Rn;
11802  let Inst{31-30}    = size;
11803  let Inst{29-24}    = {0,1,1,V,0,1};
11804  let Inst{23-22}    = opc;
11805  let Inst{21}       = 0b0;
11806  //  Inst{20-12}
11807  let Inst{11-10}    = 0b10;
11808  let Inst{9-5}      = Rn;
11809  let Inst{4-0}      = Rt;
11810
11811  let mayLoad = Inst{22};
11812  let mayStore = !not(Inst{22});
11813  let hasSideEffects = 0;
11814}
11815
11816class BaseLRCPC3IntegerLoadStorePair<bits<2> size, bits<2> opc, bits<4> opc2,
11817                                     dag oops, dag iops, string asm,
11818                                     string operands, string cstr>
11819      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
11820  bits<5> Rt2;
11821  let Inst{20-16} = Rt2;
11822  let Inst{15-12} = opc2;
11823}
11824
11825class BaseLRCPC3IntegerLoadStore<bits<2> size, bits<2> opc, dag oops, dag iops,
11826                                 string asm, string operands, string cstr>
11827      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
11828  let Inst{20-12} = 0b000000000; // imm9
11829}
11830
11831multiclass LRCPC3NEONLoadStoreUnscaledOffset<bits<2> size, bits<2> opc, RegisterClass regtype,
11832                                             dag oops, dag iops, string asm> {
11833  def i : BaseLRCPC3<size, /*V*/1, opc, oops, iops, asm, "\t$Rt, [$Rn{, $simm}]", /*cstr*/""> {
11834    bits<9> simm; // signed immediate encoded in imm9=Rt2:imm4
11835    let Inst{20-12} = simm;
11836  }
11837
11838  def a : InstAlias<asm # "\t$Rt, [$Rn]",
11839                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
11840}
11841
11842class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
11843      : BaseSIMDLdStSingle<L, /*R*/0b0, /*opcode*/0b100, asm,
11844                           "\t$Vt$Q, [$Rn]", cst, oops, iops, []>,
11845        Sched<[]> {
11846  bit Q;
11847  let Inst{31}       = 0;
11848  let Inst{30}       = Q;
11849  let Inst{23}       = 0;
11850  let Inst{20-16}    = 0b00001;
11851  let Inst{12}       = 0; // S
11852  let Inst{11-10}    = 0b01; // size
11853
11854  let mayLoad = L;
11855  let mayStore = !not(L);
11856  let hasSideEffects = 1;
11857}
11858
11859//---
11860// Instrumentation Extension (FEAT_ITE)
11861//---
11862
11863let Predicates = [HasITE] in
11864def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
11865  let Inst{20-19} = 0b01;
11866  let Inst{18-16} = 0b011;
11867  let Inst{15-12} = 0b0111;
11868  let Inst{11-8}  = 0b0010;
11869  let Inst{7-5}   = 0b111;
11870}
11871
11872// * RCWCAS family
11873// * RCW<OP> family
11874
11875//--------------------------------------------------------------------
11876// Read-Check-Write Compare And Swap family (RCWCAS[S|P|PS]?[A|L|AL]?)
11877
11878// Instruction encoding:
11879//
11880//          31 30|29  24|23|22|21|20 16|15|14 13|12 11 10|9 5|4 0
11881// RCWCAS    0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
11882// RCWSCAS   0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
11883// RCWCASP   0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
11884// RCWSCASP  0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
11885
11886// Instruction syntax:
11887//
11888// RCW[S]CAS{<order>}   <Xs>,           <Xt>,          [<Xn|SP>]
11889// RCW[S]CASP{<order>}  <Xs>, <X(s+1)>, <Xt>, <X(t+1)> [<Xn|SP>]
11890
11891class BaseRCWCASEncoding<dag oops, dag iops, string asm>
11892      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", "$out = $Rs", []>,
11893        Sched<[]> {
11894  bit Acq;
11895  bit Rel;
11896  bit SC;
11897  bit Pair;
11898  bits<5> Rs;
11899  bits<5> Rn;
11900  bits<5> Rt;
11901  let Inst{31} = 0b0;
11902  let Inst{30} = SC;
11903  let Inst{29-24} = 0b011001;
11904  let Inst{23} = Acq;
11905  let Inst{22} = Rel;
11906  let Inst{21} = 0b1;
11907  let Inst{20-16} = Rs;
11908  let Inst{15-13} = 0b000;
11909  let Inst{12-11} = 0b01;
11910  let Inst{10} = Pair;
11911  let Inst{9-5} = Rn;
11912  let Inst{4-0} = Rt;
11913  let mayLoad = 1;
11914  let mayStore = 1;
11915  let hasSideEffects = 1;
11916  let Defs = [NZCV];
11917}
11918
11919multiclass BaseRCWCAS<dag oops, dag iops, string prefix> {
11920  let Acq = 0b0, Rel = 0b0 in
11921    def "" : BaseRCWCASEncoding<oops, iops, prefix # "">;
11922  let Acq = 0b1, Rel = 0b0 in
11923    def A  : BaseRCWCASEncoding<oops, iops, prefix # "a">;
11924  let Acq = 0b0, Rel = 0b1 in
11925    def L  : BaseRCWCASEncoding<oops, iops, prefix # "l">;
11926  let Acq = 0b1, Rel = 0b1 in
11927    def AL : BaseRCWCASEncoding<oops, iops, prefix # "al">;
11928}
11929
11930multiclass ReadCheckWriteCompareAndSwap {
11931  let SC = 0b0, Pair = 0b0, Predicates = [HasTHE] in
11932    defm CAS  : BaseRCWCAS<(outs GPR64:$out),
11933                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwcas" >;
11934  let SC = 0b1, Pair = 0b0, Predicates = [HasTHE] in
11935    defm SCAS : BaseRCWCAS<(outs GPR64:$out),
11936                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwscas">;
11937  let SC = 0b0, Pair = 0b1, Predicates = [HasTHE, HasD128] in
11938    defm CASP : BaseRCWCAS<(outs XSeqPairClassOperand:$out),
11939                           (ins XSeqPairClassOperand:$Rs,
11940                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
11941                           "rcwcasp">;
11942  let SC = 0b1, Pair = 0b1, Predicates = [HasTHE, HasD128] in
11943    defm SCASP: BaseRCWCAS<(outs XSeqPairClassOperand:$out),
11944                           (ins XSeqPairClassOperand:$Rs,
11945                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
11946                           "rcwscasp">;
11947}
11948
11949//------------------------------------------------------------------
11950// Read-Check-Write <OP> family (RCW[CLR|SET|SWP][S|P|PS]?[A|L|AL]?)
11951
11952// Instruction encoding:
11953//
11954//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
11955// RCWCLR    0  0|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
11956// RCWSCLR   0  1|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
11957// RCWSET    0  0|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
11958// RCWSSET   0  1|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
11959// RCWSWP    0  0|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
11960// RCWSSWP   0  1|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
11961
11962//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
11963// RCWCLRP   0  0|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
11964// RCWSCLRP  0  1|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
11965// RCWSETP   0  0|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
11966// RCWSSETP  0  1|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
11967// RCWSWPP   0  0|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
11968// RCWSSWPP  0  1|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
11969
11970// Instruction syntax:
11971//
11972// RCW[S]<OP>{<order>}   <Xs>,  <Xt>, [<Xn|SP>]
11973// RCW[S]<OP>P{<order>}  <Xt1>, <Xt2>, [<Xn|SP>]
11974
11975class BaseRCWOPEncoding<string asm>
11976      : I<(outs GPR64:$Rt),(ins GPR64:$Rs, GPR64sp:$Rn), asm,
11977          "\t$Rs, $Rt, [$Rn]", "", []>,
11978        Sched<[]> {
11979  bit Acq;
11980  bit Rel;
11981  bit SC;
11982  bits<3> opc;
11983  bits<5> Rs;
11984  bits<5> Rn;
11985  bits<5> Rt;
11986  let Inst{31} = 0b0;
11987  let Inst{30} = SC;
11988  let Inst{29-24} = 0b111000;
11989  let Inst{23} = Acq;
11990  let Inst{22} = Rel;
11991  let Inst{21} = 0b1;
11992  let Inst{20-16} = Rs;
11993  let Inst{15} = 0b1;
11994  let Inst{14-12} = opc;
11995  let Inst{11-10} = 0b00;
11996  let Inst{9-5} = Rn;
11997  let Inst{4-0} = Rt;
11998  let mayLoad = 1;
11999  let mayStore = 1;
12000  let hasSideEffects = 1;
12001  let Defs = [NZCV];
12002  let Predicates = [HasTHE];
12003}
12004
12005class BaseRCWOPPEncoding<string asm>
12006      : I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12007          (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn), asm,
12008          "\t$Rt, $Rt2, [$Rn]", "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12009        Sched<[]> {
12010  bit Acq;
12011  bit Rel;
12012  bit SC;
12013  bits<3> opc;
12014  bits<5> Rt2;
12015  bits<5> Rn;
12016  bits<5> Rt;
12017  let Inst{31} = 0b0;
12018  let Inst{30} = SC;
12019  let Inst{29-24} = 0b011001;
12020  let Inst{23} = Acq;
12021  let Inst{22} = Rel;
12022  let Inst{21} = 0b1;
12023  let Inst{20-16} = Rt2;
12024  let Inst{15} = 0b1;
12025  let Inst{14-12} = opc;
12026  let Inst{11-10} = 0b00;
12027  let Inst{9-5} = Rn;
12028  let Inst{4-0} = Rt;
12029  let mayLoad = 1;
12030  let mayStore = 1;
12031  let hasSideEffects = 1;
12032  let Defs = [NZCV];
12033  let Predicates = [HasTHE, HasD128];
12034}
12035
12036multiclass BaseRCWOP<string prefix> {
12037  let Acq = 0b0, Rel = 0b0 in def "" : BaseRCWOPEncoding<prefix # "">;
12038  let Acq = 0b1, Rel = 0b0 in def A  : BaseRCWOPEncoding<prefix # "a">;
12039  let Acq = 0b0, Rel = 0b1 in def L  : BaseRCWOPEncoding<prefix # "l">;
12040  let Acq = 0b1, Rel = 0b1 in def AL : BaseRCWOPEncoding<prefix # "al">;
12041
12042  let Acq = 0b0, Rel = 0b0 in def P   : BaseRCWOPPEncoding<prefix # "p">;
12043  let Acq = 0b1, Rel = 0b0 in def PA  : BaseRCWOPPEncoding<prefix # "pa">;
12044  let Acq = 0b0, Rel = 0b1 in def PL  : BaseRCWOPPEncoding<prefix # "pl">;
12045  let Acq = 0b1, Rel = 0b1 in def PAL : BaseRCWOPPEncoding<prefix # "pal">;
12046}
12047
12048multiclass ReadCheckWriteOperation<bits<3> opc, string op> {
12049  let SC = 0b0, opc = opc in defm ""  : BaseRCWOP<"rcw" # ""  # op>;
12050  let SC = 0b1, opc = opc in defm S   : BaseRCWOP<"rcw" # "s" # op >;
12051}
12052
12053//---
12054// 128-bit atomic instructions (FEAT_LSE128)
12055//---
12056
12057let mayLoad = 1, mayStore = 1, hasSideEffects = 0 in
12058class LSE128Base<bits<3> op0, bits<2> AR, bit o3, string asm>
12059: I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12060    (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn),
12061    asm, "\t$Rt, $Rt2, [$Rn]",
12062    "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12063  Sched<[]> {
12064  bits<5> Rt;
12065  bits<5> Rt2;
12066  bits<5> Rn;
12067  let Inst{31-24} = 0b00011001;
12068  let Inst{23-22} = AR;
12069  let Inst{21} = 0b1;
12070  let Inst{20-16} = Rt2;
12071  let Inst{15} = o3;
12072  let Inst{14-12} = op0;
12073  let Inst{11-10} = 0b00;
12074  let Inst{9-5} = Rn;
12075  let Inst{4-0} = Rt;
12076}
12077
12078//---
12079// 128-bit System Instructions (FEAT_SYSINSTR128)
12080//---
12081
12082// Instruction encoding:
12083//
12084//          31          19|18 16|15 12|11 8|7 5|4 0
12085// SYSP      1101010101001|  op1|   Cn|  Cm|op2| Rt
12086
12087// Instruction syntax:
12088//
12089// SYSP #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>, <Xt+1>}
12090
12091class RtSystemI128<bit L, dag oops, dag iops, string asm, string operands, list<dag> pattern = []> :
12092  RtSystemI<L, oops, iops, asm, operands, pattern> {
12093  let Inst{22}    = 0b1; // override BaseSystemI
12094}
12095
12096class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inputs>
12097  : RtSystemI128<L, outputs, inputs, asm, operands> {
12098  bits<3> op1;
12099  bits<4> Cn;
12100  bits<4> Cm;
12101  bits<3> op2;
12102  let Inst{20-19} = 0b01;
12103  let Inst{18-16} = op1;
12104  let Inst{15-12} = Cn;
12105  let Inst{11-8}  = Cm;
12106  let Inst{7-5}   = op2;
12107}
12108class SystemPXtI<bit L, string asm> :
12109  BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
12110  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
12111
12112
12113//----------------------------------------------------------------------------
12114// Allow the size specifier tokens to be upper case, not just lower.
12115def : TokenAlias<".4B", ".4b">;  // Add dot product
12116def : TokenAlias<".8B", ".8b">;
12117def : TokenAlias<".4H", ".4h">;
12118def : TokenAlias<".2S", ".2s">;
12119def : TokenAlias<".1D", ".1d">;
12120def : TokenAlias<".16B", ".16b">;
12121def : TokenAlias<".8H", ".8h">;
12122def : TokenAlias<".4S", ".4s">;
12123def : TokenAlias<".2D", ".2d">;
12124def : TokenAlias<".1Q", ".1q">;
12125def : TokenAlias<".2H", ".2h">;
12126def : TokenAlias<".B", ".b">;
12127def : TokenAlias<".H", ".h">;
12128def : TokenAlias<".S", ".s">;
12129def : TokenAlias<".D", ".d">;
12130def : TokenAlias<".Q", ".q">;
12131