blob: 76fe443e2f5ecf7c8c7c59157a15622815410f04 [file] [log] [blame]
Tim Northover00ed9962014-03-29 10:18:08 +00001//===- ARM64InstrFormats.td - ARM64 Instruction Formats ------*- tblgen -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10//===----------------------------------------------------------------------===//
11// Describe ARM64 instructions format here
12//
13
14// Format specifies the encoding used by the instruction. This is part of the
15// ad-hoc solution used to emit machine instruction encodings by our machine
16// code emitter.
17class Format<bits<2> val> {
18 bits<2> Value = val;
19}
20
21def PseudoFrm : Format<0>;
22def NormalFrm : Format<1>; // Do we need any others?
23
24// ARM64 Instruction Format
25class ARM64Inst<Format f, string cstr> : Instruction {
26 field bits<32> Inst; // Instruction encoding.
27 // Mask of bits that cause an encoding to be UNPREDICTABLE.
28 // If a bit is set, then if the corresponding bit in the
29 // target encoding differs from its value in the "Inst" field,
30 // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31 field bits<32> Unpredictable = 0;
32 // SoftFail is the generic name for this field, but we alias it so
33 // as to make it more obvious what it means in ARM-land.
34 field bits<32> SoftFail = Unpredictable;
35 let Namespace = "ARM64";
36 Format F = f;
37 bits<2> Form = F.Value;
38 let Pattern = [];
39 let Constraints = cstr;
40}
41
42// Pseudo instructions (don't have encoding information)
43class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44 : ARM64Inst<PseudoFrm, cstr> {
45 dag OutOperandList = oops;
46 dag InOperandList = iops;
47 let Pattern = pattern;
48 let isCodeGenOnly = 1;
49}
50
51// Real instructions (have encoding information)
52class EncodedI<string cstr, list<dag> pattern> : ARM64Inst<NormalFrm, cstr> {
53 let Pattern = pattern;
54 let Size = 4;
55}
56
57// Normal instructions
58class I<dag oops, dag iops, string asm, string operands, string cstr,
59 list<dag> pattern>
60 : EncodedI<cstr, pattern> {
61 dag OutOperandList = oops;
62 dag InOperandList = iops;
63 let AsmString = !strconcat(asm, operands);
64}
65
66class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
69
70// Helper fragment for an extract of the high portion of a 128-bit vector.
71def extract_high_v16i8 :
72 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73def extract_high_v8i16 :
74 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75def extract_high_v4i32 :
76 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77def extract_high_v2i64 :
78 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80//===----------------------------------------------------------------------===//
81// Asm Operand Classes.
82//
83
84// Shifter operand for arithmetic shifted encodings.
85def ShifterOperand : AsmOperandClass {
86 let Name = "Shifter";
87}
88
89// Shifter operand for mov immediate encodings.
90def MovImm32ShifterOperand : AsmOperandClass {
91 let SuperClasses = [ShifterOperand];
92 let Name = "MovImm32Shifter";
93}
94def MovImm64ShifterOperand : AsmOperandClass {
95 let SuperClasses = [ShifterOperand];
96 let Name = "MovImm64Shifter";
97}
98
99// Shifter operand for arithmetic register shifted encodings.
100def ArithmeticShifterOperand : AsmOperandClass {
101 let SuperClasses = [ShifterOperand];
102 let Name = "ArithmeticShifter";
103}
104
105// Shifter operand for arithmetic shifted encodings for ADD/SUB instructions.
106def AddSubShifterOperand : AsmOperandClass {
107 let SuperClasses = [ArithmeticShifterOperand];
108 let Name = "AddSubShifter";
109}
110
111// Shifter operand for logical vector 128/64-bit shifted encodings.
112def LogicalVecShifterOperand : AsmOperandClass {
113 let SuperClasses = [ShifterOperand];
114 let Name = "LogicalVecShifter";
115}
116def LogicalVecHalfWordShifterOperand : AsmOperandClass {
117 let SuperClasses = [LogicalVecShifterOperand];
118 let Name = "LogicalVecHalfWordShifter";
119}
120
121// The "MSL" shifter on the vector MOVI instruction.
122def MoveVecShifterOperand : AsmOperandClass {
123 let SuperClasses = [ShifterOperand];
124 let Name = "MoveVecShifter";
125}
126
127// Extend operand for arithmetic encodings.
128def ExtendOperand : AsmOperandClass { let Name = "Extend"; }
129def ExtendOperand64 : AsmOperandClass {
130 let SuperClasses = [ExtendOperand];
131 let Name = "Extend64";
132}
133// 'extend' that's a lsl of a 64-bit register.
134def ExtendOperandLSL64 : AsmOperandClass {
135 let SuperClasses = [ExtendOperand];
136 let Name = "ExtendLSL64";
137}
138
139// 8-bit floating-point immediate encodings.
140def FPImmOperand : AsmOperandClass {
141 let Name = "FPImm";
142 let ParserMethod = "tryParseFPImm";
143}
144
145// 8-bit immediate for AdvSIMD where 64-bit values of the form:
146// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
147// are encoded as the eight bit value 'abcdefgh'.
148def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
149
150
151//===----------------------------------------------------------------------===//
152// Operand Definitions.
153//
154
155// ADR[P] instruction labels.
156def AdrpOperand : AsmOperandClass {
157 let Name = "AdrpLabel";
158 let ParserMethod = "tryParseAdrpLabel";
Bradley Smithf8230792014-04-09 14:44:12 +0000159 let DiagnosticType = "InvalidLabel";
Tim Northover00ed9962014-03-29 10:18:08 +0000160}
161def adrplabel : Operand<i64> {
162 let EncoderMethod = "getAdrLabelOpValue";
163 let PrintMethod = "printAdrpLabel";
164 let ParserMatchClass = AdrpOperand;
165}
166
167def AdrOperand : AsmOperandClass {
168 let Name = "AdrLabel";
169 let ParserMethod = "tryParseAdrLabel";
Bradley Smithf8230792014-04-09 14:44:12 +0000170 let DiagnosticType = "InvalidLabel";
Tim Northover00ed9962014-03-29 10:18:08 +0000171}
172def adrlabel : Operand<i64> {
173 let EncoderMethod = "getAdrLabelOpValue";
174 let ParserMatchClass = AdrOperand;
175}
176
177// simm9 predicate - True if the immediate is in the range [-256, 255].
178def SImm9Operand : AsmOperandClass {
179 let Name = "SImm9";
180 let DiagnosticType = "InvalidMemoryIndexedSImm9";
181}
182def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
183 let ParserMatchClass = SImm9Operand;
184}
185
186// simm7s4 predicate - True if the immediate is a multiple of 4 in the range
187// [-256, 252].
188def SImm7s4Operand : AsmOperandClass {
189 let Name = "SImm7s4";
190 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
191}
192def simm7s4 : Operand<i32> {
193 let ParserMatchClass = SImm7s4Operand;
194 let PrintMethod = "printImmScale4";
195}
196
197// simm7s8 predicate - True if the immediate is a multiple of 8 in the range
198// [-512, 504].
199def SImm7s8Operand : AsmOperandClass {
200 let Name = "SImm7s8";
201 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
202}
203def simm7s8 : Operand<i32> {
204 let ParserMatchClass = SImm7s8Operand;
205 let PrintMethod = "printImmScale8";
206}
207
208// simm7s16 predicate - True if the immediate is a multiple of 16 in the range
209// [-1024, 1008].
210def SImm7s16Operand : AsmOperandClass {
211 let Name = "SImm7s16";
212 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
213}
214def simm7s16 : Operand<i32> {
215 let ParserMatchClass = SImm7s16Operand;
216 let PrintMethod = "printImmScale16";
217}
218
219// imm0_65535 predicate - True if the immediate is in the range [0,65535].
220def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
221def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
222 return ((uint32_t)Imm) < 65536;
223}]> {
224 let ParserMatchClass = Imm0_65535Operand;
225}
226
227def Imm1_8Operand : AsmOperandClass {
228 let Name = "Imm1_8";
229 let DiagnosticType = "InvalidImm1_8";
230}
231def Imm1_16Operand : AsmOperandClass {
232 let Name = "Imm1_16";
233 let DiagnosticType = "InvalidImm1_16";
234}
235def Imm1_32Operand : AsmOperandClass {
236 let Name = "Imm1_32";
237 let DiagnosticType = "InvalidImm1_32";
238}
239def Imm1_64Operand : AsmOperandClass {
240 let Name = "Imm1_64";
241 let DiagnosticType = "InvalidImm1_64";
242}
243
244def MovZSymbolG3AsmOperand : AsmOperandClass {
245 let Name = "MovZSymbolG3";
246 let RenderMethod = "addImmOperands";
247}
248
249def movz_symbol_g3 : Operand<i32> {
250 let ParserMatchClass = MovZSymbolG3AsmOperand;
251}
252
253def MovZSymbolG2AsmOperand : AsmOperandClass {
254 let Name = "MovZSymbolG2";
255 let RenderMethod = "addImmOperands";
256}
257
258def movz_symbol_g2 : Operand<i32> {
259 let ParserMatchClass = MovZSymbolG2AsmOperand;
260}
261
262def MovZSymbolG1AsmOperand : AsmOperandClass {
263 let Name = "MovZSymbolG1";
264 let RenderMethod = "addImmOperands";
265}
266
267def movz_symbol_g1 : Operand<i32> {
268 let ParserMatchClass = MovZSymbolG1AsmOperand;
269}
270
271def MovZSymbolG0AsmOperand : AsmOperandClass {
272 let Name = "MovZSymbolG0";
273 let RenderMethod = "addImmOperands";
274}
275
276def movz_symbol_g0 : Operand<i32> {
277 let ParserMatchClass = MovZSymbolG0AsmOperand;
278}
279
280def MovKSymbolG2AsmOperand : AsmOperandClass {
281 let Name = "MovKSymbolG2";
282 let RenderMethod = "addImmOperands";
283}
284
285def movk_symbol_g2 : Operand<i32> {
286 let ParserMatchClass = MovKSymbolG2AsmOperand;
287}
288
289def MovKSymbolG1AsmOperand : AsmOperandClass {
290 let Name = "MovKSymbolG1";
291 let RenderMethod = "addImmOperands";
292}
293
294def movk_symbol_g1 : Operand<i32> {
295 let ParserMatchClass = MovKSymbolG1AsmOperand;
296}
297
298def MovKSymbolG0AsmOperand : AsmOperandClass {
299 let Name = "MovKSymbolG0";
300 let RenderMethod = "addImmOperands";
301}
302
303def movk_symbol_g0 : Operand<i32> {
304 let ParserMatchClass = MovKSymbolG0AsmOperand;
305}
306
Tim Northover80a70a22014-04-15 13:59:57 +0000307class fixedpoint_i32<ValueType FloatVT>
308 : Operand<FloatVT>,
309 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
Tim Northover00ed9962014-03-29 10:18:08 +0000310 let EncoderMethod = "getFixedPointScaleOpValue";
Bradley Smitheb4ca042014-04-09 14:43:35 +0000311 let DecoderMethod = "DecodeFixedPointScaleImm32";
Tim Northover00ed9962014-03-29 10:18:08 +0000312 let ParserMatchClass = Imm1_32Operand;
313}
Tim Northover80a70a22014-04-15 13:59:57 +0000314
315class fixedpoint_i64<ValueType FloatVT>
316 : Operand<FloatVT>,
317 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
Tim Northover00ed9962014-03-29 10:18:08 +0000318 let EncoderMethod = "getFixedPointScaleOpValue";
Bradley Smitheb4ca042014-04-09 14:43:35 +0000319 let DecoderMethod = "DecodeFixedPointScaleImm64";
Tim Northover00ed9962014-03-29 10:18:08 +0000320 let ParserMatchClass = Imm1_64Operand;
321}
322
Tim Northover80a70a22014-04-15 13:59:57 +0000323def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
324def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
325
326def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
327def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
328
Tim Northover00ed9962014-03-29 10:18:08 +0000329def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
330 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
331}]> {
332 let EncoderMethod = "getVecShiftR8OpValue";
333 let DecoderMethod = "DecodeVecShiftR8Imm";
334 let ParserMatchClass = Imm1_8Operand;
335}
336def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
337 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
338}]> {
339 let EncoderMethod = "getVecShiftR16OpValue";
340 let DecoderMethod = "DecodeVecShiftR16Imm";
341 let ParserMatchClass = Imm1_16Operand;
342}
343def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
344 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
345}]> {
346 let EncoderMethod = "getVecShiftR16OpValue";
347 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
348 let ParserMatchClass = Imm1_8Operand;
349}
350def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
351 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
352}]> {
353 let EncoderMethod = "getVecShiftR32OpValue";
354 let DecoderMethod = "DecodeVecShiftR32Imm";
355 let ParserMatchClass = Imm1_32Operand;
356}
357def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
358 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
359}]> {
360 let EncoderMethod = "getVecShiftR32OpValue";
361 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
362 let ParserMatchClass = Imm1_16Operand;
363}
364def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
365 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
366}]> {
367 let EncoderMethod = "getVecShiftR64OpValue";
368 let DecoderMethod = "DecodeVecShiftR64Imm";
369 let ParserMatchClass = Imm1_64Operand;
370}
371def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
372 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
373}]> {
374 let EncoderMethod = "getVecShiftR64OpValue";
375 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
376 let ParserMatchClass = Imm1_32Operand;
377}
378
379def Imm0_7Operand : AsmOperandClass { let Name = "Imm0_7"; }
380def Imm0_15Operand : AsmOperandClass { let Name = "Imm0_15"; }
381def Imm0_31Operand : AsmOperandClass { let Name = "Imm0_31"; }
382def Imm0_63Operand : AsmOperandClass { let Name = "Imm0_63"; }
383
384def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
385 return (((uint32_t)Imm) < 8);
386}]> {
387 let EncoderMethod = "getVecShiftL8OpValue";
388 let DecoderMethod = "DecodeVecShiftL8Imm";
389 let ParserMatchClass = Imm0_7Operand;
390}
391def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
392 return (((uint32_t)Imm) < 16);
393}]> {
394 let EncoderMethod = "getVecShiftL16OpValue";
395 let DecoderMethod = "DecodeVecShiftL16Imm";
396 let ParserMatchClass = Imm0_15Operand;
397}
398def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
399 return (((uint32_t)Imm) < 32);
400}]> {
401 let EncoderMethod = "getVecShiftL32OpValue";
402 let DecoderMethod = "DecodeVecShiftL32Imm";
403 let ParserMatchClass = Imm0_31Operand;
404}
405def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
406 return (((uint32_t)Imm) < 64);
407}]> {
408 let EncoderMethod = "getVecShiftL64OpValue";
409 let DecoderMethod = "DecodeVecShiftL64Imm";
410 let ParserMatchClass = Imm0_63Operand;
411}
412
413
414// Crazy immediate formats used by 32-bit and 64-bit logical immediate
415// instructions for splatting repeating bit patterns across the immediate.
416def logical_imm32_XFORM : SDNodeXForm<imm, [{
417 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
418 return CurDAG->getTargetConstant(enc, MVT::i32);
419}]>;
420def logical_imm64_XFORM : SDNodeXForm<imm, [{
421 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
422 return CurDAG->getTargetConstant(enc, MVT::i32);
423}]>;
424
425def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
426def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
427def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
428 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
429}], logical_imm32_XFORM> {
430 let PrintMethod = "printLogicalImm32";
431 let ParserMatchClass = LogicalImm32Operand;
432}
433def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
434 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
435}], logical_imm64_XFORM> {
436 let PrintMethod = "printLogicalImm64";
437 let ParserMatchClass = LogicalImm64Operand;
438}
439
440// imm0_255 predicate - True if the immediate is in the range [0,255].
441def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
442def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
443 return ((uint32_t)Imm) < 256;
444}]> {
445 let ParserMatchClass = Imm0_255Operand;
446}
447
448// imm0_127 predicate - True if the immediate is in the range [0,127]
449def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
450def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
451 return ((uint32_t)Imm) < 128;
452}]> {
453 let ParserMatchClass = Imm0_127Operand;
454}
455
Tim Northover2ad88d32014-04-03 09:26:16 +0000456// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
457// for all shift-amounts.
458
Tim Northover00ed9962014-03-29 10:18:08 +0000459// imm0_63 predicate - True if the immediate is in the range [0,63]
Tim Northover00ed9962014-03-29 10:18:08 +0000460def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
461 return ((uint64_t)Imm) < 64;
462}]> {
463 let ParserMatchClass = Imm0_63Operand;
464}
465
Tim Northover2ad88d32014-04-03 09:26:16 +0000466// imm0_31 predicate - True if the immediate is in the range [0,31]
467def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
Tim Northover00ed9962014-03-29 10:18:08 +0000468 return ((uint64_t)Imm) < 32;
469}]> {
470 let ParserMatchClass = Imm0_31Operand;
471}
472
Tim Northover2ad88d32014-04-03 09:26:16 +0000473// imm0_15 predicate - True if the immediate is in the range [0,15]
474def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
Tim Northover00ed9962014-03-29 10:18:08 +0000475 return ((uint64_t)Imm) < 16;
476}]> {
477 let ParserMatchClass = Imm0_15Operand;
478}
479
Tim Northover00ed9962014-03-29 10:18:08 +0000480// imm0_7 predicate - True if the immediate is in the range [0,7]
Tim Northover2ad88d32014-04-03 09:26:16 +0000481def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
482 return ((uint64_t)Imm) < 8;
Tim Northover00ed9962014-03-29 10:18:08 +0000483}]> {
484 let ParserMatchClass = Imm0_7Operand;
485}
486
487// An arithmetic shifter operand:
488// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
489// {5-0} - imm6
490def arith_shift : Operand<i32> {
491 let PrintMethod = "printShifter";
492 let ParserMatchClass = ArithmeticShifterOperand;
493}
494
495class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
496 : Operand<Ty>,
497 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
498 let PrintMethod = "printShiftedRegister";
499 let MIOperandInfo = (ops regclass, arith_shift);
500}
501
502def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
503def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
504
505// An arithmetic shifter operand:
506// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
507// {5-0} - imm6
508def logical_shift : Operand<i32> {
509 let PrintMethod = "printShifter";
510 let ParserMatchClass = ShifterOperand;
511}
512
513class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
514 : Operand<Ty>,
515 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
516 let PrintMethod = "printShiftedRegister";
517 let MIOperandInfo = (ops regclass, logical_shift);
518}
519
520def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
521def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
522
523// A logical vector shifter operand:
524// {7-6} - shift type: 00 = lsl
525// {5-0} - imm6: #0, #8, #16, or #24
526def logical_vec_shift : Operand<i32> {
527 let PrintMethod = "printShifter";
528 let EncoderMethod = "getVecShifterOpValue";
529 let ParserMatchClass = LogicalVecShifterOperand;
530}
531
532// A logical vector half-word shifter operand:
533// {7-6} - shift type: 00 = lsl
534// {5-0} - imm6: #0 or #8
535def logical_vec_hw_shift : Operand<i32> {
536 let PrintMethod = "printShifter";
537 let EncoderMethod = "getVecShifterOpValue";
538 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
539}
540
541// A vector move shifter operand:
542// {0} - imm1: #8 or #16
543def move_vec_shift : Operand<i32> {
544 let PrintMethod = "printShifter";
545 let EncoderMethod = "getMoveVecShifterOpValue";
546 let ParserMatchClass = MoveVecShifterOperand;
547}
548
549// An ADD/SUB immediate shifter operand:
550// {7-6} - shift type: 00 = lsl
551// {5-0} - imm6: #0 or #12
552def addsub_shift : Operand<i32> {
553 let ParserMatchClass = AddSubShifterOperand;
554}
555
556class addsub_shifted_imm<ValueType Ty>
557 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
558 let PrintMethod = "printAddSubImm";
559 let EncoderMethod = "getAddSubImmOpValue";
560 let MIOperandInfo = (ops i32imm, addsub_shift);
561}
562
563def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
564def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
565
566class neg_addsub_shifted_imm<ValueType Ty>
567 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
568 let PrintMethod = "printAddSubImm";
569 let EncoderMethod = "getAddSubImmOpValue";
570 let MIOperandInfo = (ops i32imm, addsub_shift);
571}
572
573def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
574def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
575
576// An extend operand:
577// {5-3} - extend type
578// {2-0} - imm3
579def arith_extend : Operand<i32> {
580 let PrintMethod = "printExtend";
581 let ParserMatchClass = ExtendOperand;
582}
583def arith_extend64 : Operand<i32> {
584 let PrintMethod = "printExtend";
585 let ParserMatchClass = ExtendOperand64;
586}
587
588// 'extend' that's a lsl of a 64-bit register.
589def arith_extendlsl64 : Operand<i32> {
590 let PrintMethod = "printExtend";
591 let ParserMatchClass = ExtendOperandLSL64;
592}
593
594class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
595 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
596 let PrintMethod = "printExtendedRegister";
597 let MIOperandInfo = (ops GPR32, arith_extend);
598}
599
600class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
601 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
602 let PrintMethod = "printExtendedRegister";
603 let MIOperandInfo = (ops GPR32, arith_extend64);
604}
605
606// Floating-point immediate.
607def fpimm32 : Operand<f32>,
608 PatLeaf<(f32 fpimm), [{
609 return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
610 }], SDNodeXForm<fpimm, [{
611 APFloat InVal = N->getValueAPF();
612 uint32_t enc = ARM64_AM::getFP32Imm(InVal);
613 return CurDAG->getTargetConstant(enc, MVT::i32);
614 }]>> {
615 let ParserMatchClass = FPImmOperand;
616 let PrintMethod = "printFPImmOperand";
617}
618def fpimm64 : Operand<f64>,
619 PatLeaf<(f64 fpimm), [{
620 return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
621 }], SDNodeXForm<fpimm, [{
622 APFloat InVal = N->getValueAPF();
623 uint32_t enc = ARM64_AM::getFP64Imm(InVal);
624 return CurDAG->getTargetConstant(enc, MVT::i32);
625 }]>> {
626 let ParserMatchClass = FPImmOperand;
627 let PrintMethod = "printFPImmOperand";
628}
629
630def fpimm8 : Operand<i32> {
631 let ParserMatchClass = FPImmOperand;
632 let PrintMethod = "printFPImmOperand";
633}
634
635def fpimm0 : PatLeaf<(fpimm), [{
636 return N->isExactlyValue(+0.0);
637}]>;
638
639// 8-bit immediate for AdvSIMD where 64-bit values of the form:
640// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
641// are encoded as the eight bit value 'abcdefgh'.
642def simdimmtype10 : Operand<i32>,
643 PatLeaf<(f64 fpimm), [{
644 return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
645 .bitcastToAPInt()
646 .getZExtValue());
647 }], SDNodeXForm<fpimm, [{
648 APFloat InVal = N->getValueAPF();
649 uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
650 .bitcastToAPInt()
651 .getZExtValue());
652 return CurDAG->getTargetConstant(enc, MVT::i32);
653 }]>> {
654 let ParserMatchClass = SIMDImmType10Operand;
655 let PrintMethod = "printSIMDType10Operand";
656}
657
658
659//---
Alp Toker16f98b22014-04-09 14:47:27 +0000660// System management
Tim Northover00ed9962014-03-29 10:18:08 +0000661//---
662
663// Base encoding for system instruction operands.
664let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
665class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
666 : I<oops, iops, asm, operands, "", []> {
667 let Inst{31-22} = 0b1101010100;
668 let Inst{21} = L;
669}
670
671// System instructions which do not have an Rt register.
672class SimpleSystemI<bit L, dag iops, string asm, string operands>
673 : BaseSystemI<L, (outs), iops, asm, operands> {
674 let Inst{4-0} = 0b11111;
675}
676
677// System instructions which have an Rt register.
678class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
679 : BaseSystemI<L, oops, iops, asm, operands>,
680 Sched<[WriteSys]> {
681 bits<5> Rt;
682 let Inst{4-0} = Rt;
683}
684
685// Hint instructions that take both a CRm and a 3-bit immediate.
686class HintI<string mnemonic>
687 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
688 Sched<[WriteHint]> {
689 bits <7> imm;
690 let Inst{20-12} = 0b000110010;
691 let Inst{11-5} = imm;
692}
693
694// System instructions taking a single literal operand which encodes into
695// CRm. op2 differentiates the opcodes.
696def BarrierAsmOperand : AsmOperandClass {
697 let Name = "Barrier";
698 let ParserMethod = "tryParseBarrierOperand";
699}
700def barrier_op : Operand<i32> {
701 let PrintMethod = "printBarrierOption";
702 let ParserMatchClass = BarrierAsmOperand;
703}
704class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
705 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
706 Sched<[WriteBarrier]> {
707 bits<4> CRm;
708 let Inst{20-12} = 0b000110011;
709 let Inst{11-8} = CRm;
710 let Inst{7-5} = opc;
711}
712
Bradley Smith08c391c2014-04-09 14:42:36 +0000713// MRS/MSR system instructions. These have different operand classes because
714// a different subset of registers can be accessed through each instruction.
715def MRSSystemRegisterOperand : AsmOperandClass {
716 let Name = "MRSSystemRegister";
Bradley Smithe8b41662014-04-09 14:43:06 +0000717 let ParserMethod = "tryParseSysReg";
Tim Northover00ed9962014-03-29 10:18:08 +0000718}
719// concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
Bradley Smith08c391c2014-04-09 14:42:36 +0000720def mrs_sysreg_op : Operand<i32> {
721 let ParserMatchClass = MRSSystemRegisterOperand;
722 let DecoderMethod = "DecodeMRSSystemRegister";
723 let PrintMethod = "printMRSSystemRegister";
Tim Northover00ed9962014-03-29 10:18:08 +0000724}
725
Bradley Smith08c391c2014-04-09 14:42:36 +0000726def MSRSystemRegisterOperand : AsmOperandClass {
727 let Name = "MSRSystemRegister";
Bradley Smithe8b41662014-04-09 14:43:06 +0000728 let ParserMethod = "tryParseSysReg";
Bradley Smith08c391c2014-04-09 14:42:36 +0000729}
730def msr_sysreg_op : Operand<i32> {
731 let ParserMatchClass = MSRSystemRegisterOperand;
732 let DecoderMethod = "DecodeMSRSystemRegister";
733 let PrintMethod = "printMSRSystemRegister";
734}
735
736class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
Tim Northover00ed9962014-03-29 10:18:08 +0000737 "mrs", "\t$Rt, $systemreg"> {
738 bits<15> systemreg;
739 let Inst{20} = 1;
740 let Inst{19-5} = systemreg;
741}
742
743// FIXME: Some of these def CPSR, others don't. Best way to model that?
744// Explicitly modeling each of the system register as a register class
745// would do it, but feels like overkill at this point.
Bradley Smith08c391c2014-04-09 14:42:36 +0000746class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
Tim Northover00ed9962014-03-29 10:18:08 +0000747 "msr", "\t$systemreg, $Rt"> {
748 bits<15> systemreg;
749 let Inst{20} = 1;
750 let Inst{19-5} = systemreg;
751}
752
753def SystemCPSRFieldOperand : AsmOperandClass {
754 let Name = "SystemCPSRField";
Bradley Smithe8b41662014-04-09 14:43:06 +0000755 let ParserMethod = "tryParseSysReg";
Tim Northover00ed9962014-03-29 10:18:08 +0000756}
757def cpsrfield_op : Operand<i32> {
758 let ParserMatchClass = SystemCPSRFieldOperand;
759 let PrintMethod = "printSystemCPSRField";
760}
761
762let Defs = [CPSR] in
763class MSRcpsrI : SimpleSystemI<0, (ins cpsrfield_op:$cpsr_field, imm0_15:$imm),
764 "msr", "\t$cpsr_field, $imm">,
765 Sched<[WriteSys]> {
766 bits<6> cpsrfield;
767 bits<4> imm;
768 let Inst{20-19} = 0b00;
769 let Inst{18-16} = cpsrfield{5-3};
770 let Inst{15-12} = 0b0100;
771 let Inst{11-8} = imm;
772 let Inst{7-5} = cpsrfield{2-0};
773
774 let DecoderMethod = "DecodeSystemCPSRInstruction";
775}
776
777// SYS and SYSL generic system instructions.
778def SysCRAsmOperand : AsmOperandClass {
779 let Name = "SysCR";
780 let ParserMethod = "tryParseSysCROperand";
781}
782
783def sys_cr_op : Operand<i32> {
784 let PrintMethod = "printSysCROperand";
785 let ParserMatchClass = SysCRAsmOperand;
786}
787
Tim Northover00ed9962014-03-29 10:18:08 +0000788class SystemXtI<bit L, string asm>
789 : RtSystemI<L, (outs),
790 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
791 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
792 bits<3> op1;
793 bits<4> Cn;
794 bits<4> Cm;
795 bits<3> op2;
796 let Inst{20-19} = 0b01;
797 let Inst{18-16} = op1;
798 let Inst{15-12} = Cn;
799 let Inst{11-8} = Cm;
800 let Inst{7-5} = op2;
801}
802
803class SystemLXtI<bit L, string asm>
804 : RtSystemI<L, (outs),
805 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
806 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
807 bits<3> op1;
808 bits<4> Cn;
809 bits<4> Cm;
810 bits<3> op2;
811 let Inst{20-19} = 0b01;
812 let Inst{18-16} = op1;
813 let Inst{15-12} = Cn;
814 let Inst{11-8} = Cm;
815 let Inst{7-5} = op2;
816}
817
818
819// Branch (register) instructions:
820//
821// case opc of
822// 0001 blr
823// 0000 br
824// 0101 dret
825// 0100 eret
826// 0010 ret
827// otherwise UNDEFINED
828class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
829 string operands, list<dag> pattern>
830 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
831 let Inst{31-25} = 0b1101011;
832 let Inst{24-21} = opc;
833 let Inst{20-16} = 0b11111;
834 let Inst{15-10} = 0b000000;
835 let Inst{4-0} = 0b00000;
836}
837
838class BranchReg<bits<4> opc, string asm, list<dag> pattern>
839 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
840 bits<5> Rn;
841 let Inst{9-5} = Rn;
842}
843
844let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
845class SpecialReturn<bits<4> opc, string asm>
846 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
847 let Inst{9-5} = 0b11111;
848}
849
850//---
851// Conditional branch instruction.
852//---
853// Branch condition code.
854// 4-bit immediate. Pretty-printed as .<cc>
855def dotCcode : Operand<i32> {
856 let PrintMethod = "printDotCondCode";
857}
858
859// Conditional branch target. 19-bit immediate. The low two bits of the target
860// offset are implied zero and so are not part of the immediate.
861def BranchTarget19Operand : AsmOperandClass {
862 let Name = "BranchTarget19";
863}
864def am_brcond : Operand<OtherVT> {
865 let EncoderMethod = "getCondBranchTargetOpValue";
866 let DecoderMethod = "DecodeCondBranchTarget";
867 let PrintMethod = "printAlignedBranchTarget";
868 let ParserMatchClass = BranchTarget19Operand;
869}
870
871class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
872 "b", "$cond\t$target", "",
873 [(ARM64brcond bb:$target, imm:$cond, CPSR)]>,
874 Sched<[WriteBr]> {
875 let isBranch = 1;
876 let isTerminator = 1;
877 let Uses = [CPSR];
878
879 bits<4> cond;
880 bits<19> target;
881 let Inst{31-24} = 0b01010100;
882 let Inst{23-5} = target;
883 let Inst{4} = 0;
884 let Inst{3-0} = cond;
885}
886
887//---
888// Compare-and-branch instructions.
889//---
890class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
891 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
892 asm, "\t$Rt, $target", "",
893 [(node regtype:$Rt, bb:$target)]>,
894 Sched<[WriteBr]> {
895 let isBranch = 1;
896 let isTerminator = 1;
897
898 bits<5> Rt;
899 bits<19> target;
900 let Inst{30-25} = 0b011010;
901 let Inst{24} = op;
902 let Inst{23-5} = target;
903 let Inst{4-0} = Rt;
904}
905
906multiclass CmpBranch<bit op, string asm, SDNode node> {
907 def W : BaseCmpBranch<GPR32, op, asm, node> {
908 let Inst{31} = 0;
909 }
910 def X : BaseCmpBranch<GPR64, op, asm, node> {
911 let Inst{31} = 1;
912 }
913}
914
915//---
916// Test-bit-and-branch instructions.
917//---
918// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
919// the target offset are implied zero and so are not part of the immediate.
920def BranchTarget14Operand : AsmOperandClass {
921 let Name = "BranchTarget14";
922}
923def am_tbrcond : Operand<OtherVT> {
924 let EncoderMethod = "getTestBranchTargetOpValue";
925 let PrintMethod = "printAlignedBranchTarget";
926 let ParserMatchClass = BranchTarget14Operand;
927}
928
929class TestBranch<bit op, string asm, SDNode node>
930 : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
931 asm, "\t$Rt, $bit_off, $target", "",
932 [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
933 Sched<[WriteBr]> {
934 let isBranch = 1;
935 let isTerminator = 1;
936
937 bits<5> Rt;
938 bits<6> bit_off;
939 bits<14> target;
940
941 let Inst{31} = bit_off{5};
942 let Inst{30-25} = 0b011011;
943 let Inst{24} = op;
944 let Inst{23-19} = bit_off{4-0};
945 let Inst{18-5} = target;
946 let Inst{4-0} = Rt;
947
948 let DecoderMethod = "DecodeTestAndBranch";
949}
950
951//---
952// Unconditional branch (immediate) instructions.
953//---
954def BranchTarget26Operand : AsmOperandClass {
955 let Name = "BranchTarget26";
956}
957def am_b_target : Operand<OtherVT> {
958 let EncoderMethod = "getBranchTargetOpValue";
959 let PrintMethod = "printAlignedBranchTarget";
960 let ParserMatchClass = BranchTarget26Operand;
961}
962def am_bl_target : Operand<i64> {
963 let EncoderMethod = "getBranchTargetOpValue";
964 let PrintMethod = "printAlignedBranchTarget";
965 let ParserMatchClass = BranchTarget26Operand;
966}
967
968class BImm<bit op, dag iops, string asm, list<dag> pattern>
969 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
970 bits<26> addr;
971 let Inst{31} = op;
972 let Inst{30-26} = 0b00101;
973 let Inst{25-0} = addr;
974
975 let DecoderMethod = "DecodeUnconditionalBranch";
976}
977
978class BranchImm<bit op, string asm, list<dag> pattern>
979 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
980class CallImm<bit op, string asm, list<dag> pattern>
981 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
982
983//---
984// Basic one-operand data processing instructions.
985//---
986
987let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
988class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
989 SDPatternOperator node>
990 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
991 [(set regtype:$Rd, (node regtype:$Rn))]>,
992 Sched<[WriteI]> {
993 bits<5> Rd;
994 bits<5> Rn;
995
996 let Inst{30-13} = 0b101101011000000000;
997 let Inst{12-10} = opc;
998 let Inst{9-5} = Rn;
999 let Inst{4-0} = Rd;
1000}
1001
1002let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1003multiclass OneOperandData<bits<3> opc, string asm,
1004 SDPatternOperator node = null_frag> {
1005 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1006 let Inst{31} = 0;
1007 }
1008
1009 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1010 let Inst{31} = 1;
1011 }
1012}
1013
1014class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1015 : BaseOneOperandData<opc, GPR32, asm, node> {
1016 let Inst{31} = 0;
1017}
1018
1019class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1020 : BaseOneOperandData<opc, GPR64, asm, node> {
1021 let Inst{31} = 1;
1022}
1023
1024//---
1025// Basic two-operand data processing instructions.
1026//---
1027class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1028 list<dag> pattern>
1029 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1030 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1031 Sched<[WriteI]> {
1032 let Uses = [CPSR];
1033 bits<5> Rd;
1034 bits<5> Rn;
1035 bits<5> Rm;
1036 let Inst{30} = isSub;
1037 let Inst{28-21} = 0b11010000;
1038 let Inst{20-16} = Rm;
1039 let Inst{15-10} = 0;
1040 let Inst{9-5} = Rn;
1041 let Inst{4-0} = Rd;
1042}
1043
1044class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1045 SDNode OpNode>
1046 : BaseBaseAddSubCarry<isSub, regtype, asm,
1047 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR))]>;
1048
1049class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1050 SDNode OpNode>
1051 : BaseBaseAddSubCarry<isSub, regtype, asm,
1052 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR)),
1053 (implicit CPSR)]> {
1054 let Defs = [CPSR];
1055}
1056
1057multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1058 SDNode OpNode, SDNode OpNode_setflags> {
1059 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1060 let Inst{31} = 0;
1061 let Inst{29} = 0;
1062 }
1063 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1064 let Inst{31} = 1;
1065 let Inst{29} = 0;
1066 }
1067
1068 // Sets flags.
1069 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1070 OpNode_setflags> {
1071 let Inst{31} = 0;
1072 let Inst{29} = 1;
1073 }
1074 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1075 OpNode_setflags> {
1076 let Inst{31} = 1;
1077 let Inst{29} = 1;
1078 }
1079}
1080
1081class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1082 SDPatternOperator OpNode>
1083 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1084 asm, "\t$Rd, $Rn, $Rm", "",
1085 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1086 bits<5> Rd;
1087 bits<5> Rn;
1088 bits<5> Rm;
1089 let Inst{30-21} = 0b0011010110;
1090 let Inst{20-16} = Rm;
1091 let Inst{15-14} = 0b00;
1092 let Inst{13-10} = opc;
1093 let Inst{9-5} = Rn;
1094 let Inst{4-0} = Rd;
1095}
1096
1097class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1098 SDPatternOperator OpNode>
1099 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1100 let Inst{10} = isSigned;
1101}
1102
1103multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1104 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1105 Sched<[WriteID32]> {
1106 let Inst{31} = 0;
1107 }
1108 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1109 Sched<[WriteID64]> {
1110 let Inst{31} = 1;
1111 }
1112}
1113
Tim Northover2ad88d32014-04-03 09:26:16 +00001114class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1115 SDPatternOperator OpNode = null_frag>
Tim Northover00ed9962014-03-29 10:18:08 +00001116 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1117 Sched<[WriteIS]> {
1118 let Inst{11-10} = shift_type;
1119}
1120
1121multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
Tim Northover2ad88d32014-04-03 09:26:16 +00001122 def Wr : BaseShift<shift_type, GPR32, asm> {
Tim Northover00ed9962014-03-29 10:18:08 +00001123 let Inst{31} = 0;
1124 }
1125
1126 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1127 let Inst{31} = 1;
1128 }
Tim Northover2ad88d32014-04-03 09:26:16 +00001129
1130 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1131 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1132 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1133
1134 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1135 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1136
1137 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1138 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1139
1140 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1141 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00001142}
1143
1144class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1145 : InstAlias<asm#" $dst, $src1, $src2",
1146 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1147
1148class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1149 RegisterClass addtype, string asm,
1150 list<dag> pattern>
1151 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1152 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1153 bits<5> Rd;
1154 bits<5> Rn;
1155 bits<5> Rm;
1156 bits<5> Ra;
1157 let Inst{30-24} = 0b0011011;
1158 let Inst{23-21} = opc;
1159 let Inst{20-16} = Rm;
1160 let Inst{15} = isSub;
1161 let Inst{14-10} = Ra;
1162 let Inst{9-5} = Rn;
1163 let Inst{4-0} = Rd;
1164}
1165
1166multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1167 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1168 [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1169 Sched<[WriteIM32]> {
1170 let Inst{31} = 0;
1171 }
1172
1173 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1174 [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1175 Sched<[WriteIM64]> {
1176 let Inst{31} = 1;
1177 }
1178}
1179
1180class WideMulAccum<bit isSub, bits<3> opc, string asm,
1181 SDNode AccNode, SDNode ExtNode>
1182 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1183 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1184 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1185 Sched<[WriteIM32]> {
1186 let Inst{31} = 1;
1187}
1188
1189class MulHi<bits<3> opc, string asm, SDNode OpNode>
1190 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1191 asm, "\t$Rd, $Rn, $Rm", "",
1192 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1193 Sched<[WriteIM64]> {
1194 bits<5> Rd;
1195 bits<5> Rn;
1196 bits<5> Rm;
1197 let Inst{31-24} = 0b10011011;
1198 let Inst{23-21} = opc;
1199 let Inst{20-16} = Rm;
Bradley Smith8f906a32014-04-09 14:43:15 +00001200 let Inst{15} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001201 let Inst{9-5} = Rn;
1202 let Inst{4-0} = Rd;
Bradley Smith8f906a32014-04-09 14:43:15 +00001203
1204 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1205 // (i.e. all bits 1) but is ignored by the processor.
1206 let PostEncoderMethod = "fixMulHigh";
Tim Northover00ed9962014-03-29 10:18:08 +00001207}
1208
1209class MulAccumWAlias<string asm, Instruction inst>
1210 : InstAlias<asm#" $dst, $src1, $src2",
1211 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1212class MulAccumXAlias<string asm, Instruction inst>
1213 : InstAlias<asm#" $dst, $src1, $src2",
1214 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1215class WideMulAccumAlias<string asm, Instruction inst>
1216 : InstAlias<asm#" $dst, $src1, $src2",
1217 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1218
1219class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1220 SDPatternOperator OpNode, string asm>
1221 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1222 asm, "\t$Rd, $Rn, $Rm", "",
1223 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1224 Sched<[WriteISReg]> {
1225 bits<5> Rd;
1226 bits<5> Rn;
1227 bits<5> Rm;
1228
1229 let Inst{31} = sf;
1230 let Inst{30-21} = 0b0011010110;
1231 let Inst{20-16} = Rm;
1232 let Inst{15-13} = 0b010;
1233 let Inst{12} = C;
1234 let Inst{11-10} = sz;
1235 let Inst{9-5} = Rn;
1236 let Inst{4-0} = Rd;
1237}
1238
1239//---
1240// Address generation.
1241//---
1242
1243class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1244 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1245 pattern>,
1246 Sched<[WriteI]> {
1247 bits<5> Xd;
1248 bits<21> label;
1249 let Inst{31} = page;
1250 let Inst{30-29} = label{1-0};
1251 let Inst{28-24} = 0b10000;
1252 let Inst{23-5} = label{20-2};
1253 let Inst{4-0} = Xd;
1254
1255 let DecoderMethod = "DecodeAdrInstruction";
1256}
1257
1258//---
1259// Move immediate.
1260//---
1261
1262def movimm32_imm : Operand<i32> {
1263 let ParserMatchClass = Imm0_65535Operand;
1264 let EncoderMethod = "getMoveWideImmOpValue";
1265}
1266def movimm32_shift : Operand<i32> {
1267 let PrintMethod = "printShifter";
1268 let ParserMatchClass = MovImm32ShifterOperand;
1269}
1270def movimm64_shift : Operand<i32> {
1271 let PrintMethod = "printShifter";
1272 let ParserMatchClass = MovImm64ShifterOperand;
1273}
1274let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1275class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1276 string asm>
1277 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1278 asm, "\t$Rd, $imm$shift", "", []>,
1279 Sched<[WriteImm]> {
1280 bits<5> Rd;
1281 bits<16> imm;
1282 bits<6> shift;
1283 let Inst{30-29} = opc;
1284 let Inst{28-23} = 0b100101;
1285 let Inst{22-21} = shift{5-4};
1286 let Inst{20-5} = imm;
1287 let Inst{4-0} = Rd;
1288
1289 let DecoderMethod = "DecodeMoveImmInstruction";
1290}
1291
1292multiclass MoveImmediate<bits<2> opc, string asm> {
1293 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1294 let Inst{31} = 0;
1295 }
1296
1297 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1298 let Inst{31} = 1;
1299 }
1300}
1301
1302let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1303class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1304 string asm>
1305 : I<(outs regtype:$Rd),
1306 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1307 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1308 Sched<[WriteI]> {
1309 bits<5> Rd;
1310 bits<16> imm;
1311 bits<6> shift;
1312 let Inst{30-29} = opc;
1313 let Inst{28-23} = 0b100101;
1314 let Inst{22-21} = shift{5-4};
1315 let Inst{20-5} = imm;
1316 let Inst{4-0} = Rd;
1317
1318 let DecoderMethod = "DecodeMoveImmInstruction";
1319}
1320
1321multiclass InsertImmediate<bits<2> opc, string asm> {
1322 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1323 let Inst{31} = 0;
1324 }
1325
1326 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1327 let Inst{31} = 1;
1328 }
1329}
1330
1331//---
1332// Add/Subtract
1333//---
1334
1335class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1336 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1337 string asm, SDPatternOperator OpNode>
1338 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1339 asm, "\t$Rd, $Rn, $imm", "",
1340 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1341 Sched<[WriteI]> {
1342 bits<5> Rd;
1343 bits<5> Rn;
1344 bits<14> imm;
1345 let Inst{30} = isSub;
1346 let Inst{29} = setFlags;
1347 let Inst{28-24} = 0b10001;
1348 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1349 let Inst{21-10} = imm{11-0};
1350 let Inst{9-5} = Rn;
1351 let Inst{4-0} = Rd;
1352 let DecoderMethod = "DecodeBaseAddSubImm";
1353}
1354
1355class BaseAddSubRegPseudo<RegisterClass regtype,
1356 SDPatternOperator OpNode>
1357 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1358 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1359 Sched<[WriteI]>;
1360
1361class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1362 arith_shifted_reg shifted_regtype, string asm,
1363 SDPatternOperator OpNode>
1364 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1365 asm, "\t$Rd, $Rn, $Rm", "",
1366 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1367 Sched<[WriteISReg]> {
1368 // The operands are in order to match the 'addr' MI operands, so we
1369 // don't need an encoder method and by-name matching. Just use the default
1370 // in-order handling. Since we're using by-order, make sure the names
1371 // do not match.
1372 bits<5> dst;
1373 bits<5> src1;
1374 bits<5> src2;
1375 bits<8> shift;
1376 let Inst{30} = isSub;
1377 let Inst{29} = setFlags;
1378 let Inst{28-24} = 0b01011;
1379 let Inst{23-22} = shift{7-6};
1380 let Inst{21} = 0;
1381 let Inst{20-16} = src2;
1382 let Inst{15-10} = shift{5-0};
1383 let Inst{9-5} = src1;
1384 let Inst{4-0} = dst;
1385
1386 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1387}
1388
1389class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1390 RegisterClass src1Regtype, Operand src2Regtype,
1391 string asm, SDPatternOperator OpNode>
1392 : I<(outs dstRegtype:$R1),
1393 (ins src1Regtype:$R2, src2Regtype:$R3),
1394 asm, "\t$R1, $R2, $R3", "",
1395 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1396 Sched<[WriteIEReg]> {
1397 bits<5> Rd;
1398 bits<5> Rn;
1399 bits<5> Rm;
1400 bits<6> ext;
1401 let Inst{30} = isSub;
1402 let Inst{29} = setFlags;
1403 let Inst{28-24} = 0b01011;
1404 let Inst{23-21} = 0b001;
1405 let Inst{20-16} = Rm;
1406 let Inst{15-13} = ext{5-3};
1407 let Inst{12-10} = ext{2-0};
1408 let Inst{9-5} = Rn;
1409 let Inst{4-0} = Rd;
1410
1411 let DecoderMethod = "DecodeAddSubERegInstruction";
1412}
1413
1414let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1415class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1416 RegisterClass src1Regtype, RegisterClass src2Regtype,
1417 Operand ext_op, string asm>
1418 : I<(outs dstRegtype:$Rd),
1419 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1420 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1421 Sched<[WriteIEReg]> {
1422 bits<5> Rd;
1423 bits<5> Rn;
1424 bits<5> Rm;
1425 bits<6> ext;
1426 let Inst{30} = isSub;
1427 let Inst{29} = setFlags;
1428 let Inst{28-24} = 0b01011;
1429 let Inst{23-21} = 0b001;
1430 let Inst{20-16} = Rm;
1431 let Inst{15} = ext{5};
1432 let Inst{12-10} = ext{2-0};
1433 let Inst{9-5} = Rn;
1434 let Inst{4-0} = Rd;
1435
1436 let DecoderMethod = "DecodeAddSubERegInstruction";
1437}
1438
1439// Aliases for register+register add/subtract.
1440class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1441 RegisterClass src1Regtype, RegisterClass src2Regtype,
1442 int shiftExt>
1443 : InstAlias<asm#" $dst, $src1, $src2",
1444 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1445 shiftExt)>;
1446
1447multiclass AddSub<bit isSub, string mnemonic,
1448 SDPatternOperator OpNode = null_frag> {
1449 let hasSideEffects = 0 in {
1450 // Add/Subtract immediate
1451 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1452 mnemonic, OpNode> {
1453 let Inst{31} = 0;
1454 }
1455 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1456 mnemonic, OpNode> {
1457 let Inst{31} = 1;
1458 }
1459
1460 // Add/Subtract register - Only used for CodeGen
1461 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1462 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1463
1464 // Add/Subtract shifted register
1465 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1466 OpNode> {
1467 let Inst{31} = 0;
1468 }
1469 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1470 OpNode> {
1471 let Inst{31} = 1;
1472 }
1473 }
1474
1475 // Add/Subtract extended register
1476 let AddedComplexity = 1, hasSideEffects = 0 in {
1477 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1478 arith_extended_reg32<i32>, mnemonic, OpNode> {
1479 let Inst{31} = 0;
1480 }
1481 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1482 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1483 let Inst{31} = 1;
1484 }
1485 }
1486
1487 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1488 arith_extendlsl64, mnemonic> {
1489 // UXTX and SXTX only.
1490 let Inst{14-13} = 0b11;
1491 let Inst{31} = 1;
1492 }
1493
1494 // Register/register aliases with no shift when SP is not used.
1495 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1496 GPR32, GPR32, GPR32, 0>;
1497 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1498 GPR64, GPR64, GPR64, 0>;
1499
1500 // Register/register aliases with no shift when either the destination or
1501 // first source register is SP. This relies on the shifted register aliases
1502 // above matching first in the case when SP is not used.
1503 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1504 GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1505 def : AddSubRegAlias<mnemonic,
1506 !cast<Instruction>(NAME#"Xrx64"),
1507 GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1508}
1509
1510multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1511 let isCompare = 1, Defs = [CPSR] in {
1512 // Add/Subtract immediate
1513 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1514 mnemonic, OpNode> {
1515 let Inst{31} = 0;
1516 }
1517 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1518 mnemonic, OpNode> {
1519 let Inst{31} = 1;
1520 }
1521
1522 // Add/Subtract register
1523 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1524 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1525
1526 // Add/Subtract shifted register
1527 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1528 OpNode> {
1529 let Inst{31} = 0;
1530 }
1531 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1532 OpNode> {
1533 let Inst{31} = 1;
1534 }
1535
1536 // Add/Subtract extended register
1537 let AddedComplexity = 1 in {
1538 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1539 arith_extended_reg32<i32>, mnemonic, OpNode> {
1540 let Inst{31} = 0;
1541 }
1542 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1543 arith_extended_reg32<i64>, mnemonic, OpNode> {
1544 let Inst{31} = 1;
1545 }
1546 }
1547
1548 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1549 arith_extendlsl64, mnemonic> {
1550 // UXTX and SXTX only.
1551 let Inst{14-13} = 0b11;
1552 let Inst{31} = 1;
1553 }
1554 } // Defs = [CPSR]
1555
1556 // Register/register aliases with no shift when SP is not used.
1557 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1558 GPR32, GPR32, GPR32, 0>;
1559 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1560 GPR64, GPR64, GPR64, 0>;
1561
1562 // Register/register aliases with no shift when the first source register
1563 // is SP. This relies on the shifted register aliases above matching first
1564 // in the case when SP is not used.
1565 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1566 GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1567 def : AddSubRegAlias<mnemonic,
1568 !cast<Instruction>(NAME#"Xrx64"),
1569 GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1570}
1571
1572//---
1573// Extract
1574//---
1575def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
Tim Northover2ad88d32014-04-03 09:26:16 +00001576 SDTCisPtrTy<3>]>;
Tim Northover00ed9962014-03-29 10:18:08 +00001577def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1578
1579class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1580 list<dag> patterns>
1581 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1582 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1583 Sched<[WriteExtr, ReadExtrHi]> {
1584 bits<5> Rd;
1585 bits<5> Rn;
1586 bits<5> Rm;
1587 bits<6> imm;
1588
1589 let Inst{30-23} = 0b00100111;
1590 let Inst{21} = 0;
1591 let Inst{20-16} = Rm;
1592 let Inst{15-10} = imm;
1593 let Inst{9-5} = Rn;
1594 let Inst{4-0} = Rd;
1595}
1596
1597multiclass ExtractImm<string asm> {
1598 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1599 [(set GPR32:$Rd,
1600 (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1601 let Inst{31} = 0;
1602 let Inst{22} = 0;
Bradley Smithdb7b9b12014-04-09 14:43:31 +00001603 // imm<5> must be zero.
1604 let imm{5} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001605 }
1606 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1607 [(set GPR64:$Rd,
1608 (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1609
1610 let Inst{31} = 1;
1611 let Inst{22} = 1;
1612 }
1613}
1614
1615//---
1616// Bitfield
1617//---
1618
1619let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1620class BaseBitfieldImm<bits<2> opc,
1621 RegisterClass regtype, Operand imm_type, string asm>
1622 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1623 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1624 Sched<[WriteIS]> {
1625 bits<5> Rd;
1626 bits<5> Rn;
1627 bits<6> immr;
1628 bits<6> imms;
1629
1630 let Inst{30-29} = opc;
1631 let Inst{28-23} = 0b100110;
1632 let Inst{21-16} = immr;
1633 let Inst{15-10} = imms;
1634 let Inst{9-5} = Rn;
1635 let Inst{4-0} = Rd;
1636}
1637
1638multiclass BitfieldImm<bits<2> opc, string asm> {
1639 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1640 let Inst{31} = 0;
1641 let Inst{22} = 0;
Bradley Smith7525b472014-04-09 14:43:24 +00001642 // imms<5> and immr<5> must be zero, else ReservedValue().
1643 let Inst{21} = 0;
1644 let Inst{15} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001645 }
1646 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1647 let Inst{31} = 1;
1648 let Inst{22} = 1;
1649 }
1650}
1651
1652let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1653class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1654 RegisterClass regtype, Operand imm_type, string asm>
1655 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1656 imm_type:$imms),
1657 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1658 Sched<[WriteIS]> {
1659 bits<5> Rd;
1660 bits<5> Rn;
1661 bits<6> immr;
1662 bits<6> imms;
1663
1664 let Inst{30-29} = opc;
1665 let Inst{28-23} = 0b100110;
1666 let Inst{21-16} = immr;
1667 let Inst{15-10} = imms;
1668 let Inst{9-5} = Rn;
1669 let Inst{4-0} = Rd;
1670}
1671
1672multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1673 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1674 let Inst{31} = 0;
1675 let Inst{22} = 0;
Bradley Smith7525b472014-04-09 14:43:24 +00001676 // imms<5> and immr<5> must be zero, else ReservedValue().
1677 let Inst{21} = 0;
1678 let Inst{15} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001679 }
1680 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1681 let Inst{31} = 1;
1682 let Inst{22} = 1;
1683 }
1684}
1685
1686//---
1687// Logical
1688//---
1689
1690// Logical (immediate)
1691class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1692 RegisterClass sregtype, Operand imm_type, string asm,
1693 list<dag> pattern>
1694 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1695 asm, "\t$Rd, $Rn, $imm", "", pattern>,
1696 Sched<[WriteI]> {
1697 bits<5> Rd;
1698 bits<5> Rn;
1699 bits<13> imm;
1700 let Inst{30-29} = opc;
1701 let Inst{28-23} = 0b100100;
1702 let Inst{22} = imm{12};
1703 let Inst{21-16} = imm{11-6};
1704 let Inst{15-10} = imm{5-0};
1705 let Inst{9-5} = Rn;
1706 let Inst{4-0} = Rd;
1707
1708 let DecoderMethod = "DecodeLogicalImmInstruction";
1709}
1710
1711// Logical (shifted register)
1712class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1713 logical_shifted_reg shifted_regtype, string asm,
1714 list<dag> pattern>
1715 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1716 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1717 Sched<[WriteISReg]> {
1718 // The operands are in order to match the 'addr' MI operands, so we
1719 // don't need an encoder method and by-name matching. Just use the default
1720 // in-order handling. Since we're using by-order, make sure the names
1721 // do not match.
1722 bits<5> dst;
1723 bits<5> src1;
1724 bits<5> src2;
1725 bits<8> shift;
1726 let Inst{30-29} = opc;
1727 let Inst{28-24} = 0b01010;
1728 let Inst{23-22} = shift{7-6};
1729 let Inst{21} = N;
1730 let Inst{20-16} = src2;
1731 let Inst{15-10} = shift{5-0};
1732 let Inst{9-5} = src1;
1733 let Inst{4-0} = dst;
1734
1735 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1736}
1737
1738// Aliases for register+register logical instructions.
1739class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1740 : InstAlias<asm#" $dst, $src1, $src2",
1741 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1742
1743let AddedComplexity = 6 in
1744multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1745 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1746 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1747 logical_imm32:$imm))]> {
1748 let Inst{31} = 0;
1749 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1750 }
1751 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1752 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1753 logical_imm64:$imm))]> {
1754 let Inst{31} = 1;
1755 }
1756}
1757
1758multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1759 let isCompare = 1, Defs = [CPSR] in {
1760 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1761 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1762 let Inst{31} = 0;
1763 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1764 }
1765 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1766 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1767 let Inst{31} = 1;
1768 }
1769 } // end Defs = [CPSR]
1770}
1771
1772class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1773 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1774 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1775 Sched<[WriteI]>;
1776
1777// Split from LogicalImm as not all instructions have both.
1778multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1779 SDPatternOperator OpNode> {
1780 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1781 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1782
1783 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1784 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1785 logical_shifted_reg32:$Rm))]> {
1786 let Inst{31} = 0;
1787 }
1788 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1789 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1790 logical_shifted_reg64:$Rm))]> {
1791 let Inst{31} = 1;
1792 }
1793
1794 def : LogicalRegAlias<mnemonic,
1795 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1796 def : LogicalRegAlias<mnemonic,
1797 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1798}
1799
1800// Split from LogicalReg to allow setting CPSR Defs
1801multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic> {
1802 let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1803 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, []>{
1804 let Inst{31} = 0;
1805 }
1806 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, []>{
1807 let Inst{31} = 1;
1808 }
1809 } // Defs = [CPSR]
1810
1811 def : LogicalRegAlias<mnemonic,
1812 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1813 def : LogicalRegAlias<mnemonic,
1814 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1815}
1816
1817//---
1818// Conditionally set flags
1819//---
1820
1821// Condition code.
1822// 4-bit immediate. Pretty-printed as <cc>
1823def ccode : Operand<i32> {
1824 let PrintMethod = "printCondCode";
1825}
1826
1827let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1828class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1829 : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1830 asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1831 Sched<[WriteI]> {
1832 let Uses = [CPSR];
1833 let Defs = [CPSR];
1834
1835 bits<5> Rn;
1836 bits<5> imm;
1837 bits<4> nzcv;
1838 bits<4> cond;
1839
1840 let Inst{30} = op;
1841 let Inst{29-21} = 0b111010010;
1842 let Inst{20-16} = imm;
1843 let Inst{15-12} = cond;
1844 let Inst{11-10} = 0b10;
1845 let Inst{9-5} = Rn;
1846 let Inst{4} = 0b0;
1847 let Inst{3-0} = nzcv;
1848}
1849
1850multiclass CondSetFlagsImm<bit op, string asm> {
1851 def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1852 let Inst{31} = 0;
1853 }
1854 def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1855 let Inst{31} = 1;
1856 }
1857}
1858
1859let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1860class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1861 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1862 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1863 Sched<[WriteI]> {
1864 let Uses = [CPSR];
1865 let Defs = [CPSR];
1866
1867 bits<5> Rn;
1868 bits<5> Rm;
1869 bits<4> nzcv;
1870 bits<4> cond;
1871
1872 let Inst{30} = op;
1873 let Inst{29-21} = 0b111010010;
1874 let Inst{20-16} = Rm;
1875 let Inst{15-12} = cond;
1876 let Inst{11-10} = 0b00;
1877 let Inst{9-5} = Rn;
1878 let Inst{4} = 0b0;
1879 let Inst{3-0} = nzcv;
1880}
1881
1882multiclass CondSetFlagsReg<bit op, string asm> {
1883 def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1884 let Inst{31} = 0;
1885 }
1886 def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1887 let Inst{31} = 1;
1888 }
1889}
1890
1891//---
1892// Conditional select
1893//---
1894
1895class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1896 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1897 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1898 [(set regtype:$Rd,
1899 (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
1900 Sched<[WriteI]> {
1901 let Uses = [CPSR];
1902
1903 bits<5> Rd;
1904 bits<5> Rn;
1905 bits<5> Rm;
1906 bits<4> cond;
1907
1908 let Inst{30} = op;
1909 let Inst{29-21} = 0b011010100;
1910 let Inst{20-16} = Rm;
1911 let Inst{15-12} = cond;
1912 let Inst{11-10} = op2;
1913 let Inst{9-5} = Rn;
1914 let Inst{4-0} = Rd;
1915}
1916
1917multiclass CondSelect<bit op, bits<2> op2, string asm> {
1918 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1919 let Inst{31} = 0;
1920 }
1921 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1922 let Inst{31} = 1;
1923 }
1924}
1925
1926class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1927 PatFrag frag>
1928 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1929 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1930 [(set regtype:$Rd,
1931 (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1932 (i32 imm:$cond), CPSR))]>,
1933 Sched<[WriteI]> {
1934 let Uses = [CPSR];
1935
1936 bits<5> Rd;
1937 bits<5> Rn;
1938 bits<5> Rm;
1939 bits<4> cond;
1940
1941 let Inst{30} = op;
1942 let Inst{29-21} = 0b011010100;
1943 let Inst{20-16} = Rm;
1944 let Inst{15-12} = cond;
1945 let Inst{11-10} = op2;
1946 let Inst{9-5} = Rn;
1947 let Inst{4-0} = Rd;
1948}
1949
Tim Northover0d7bd4f2014-04-14 12:51:02 +00001950def inv_cond_XFORM : SDNodeXForm<imm, [{
1951 ARM64CC::CondCode CC = static_cast<ARM64CC::CondCode>(N->getZExtValue());
1952 return CurDAG->getTargetConstant(ARM64CC::getInvertedCondCode(CC), MVT::i32);
1953}]>;
1954
Tim Northover00ed9962014-03-29 10:18:08 +00001955multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1956 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1957 let Inst{31} = 0;
1958 }
1959 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1960 let Inst{31} = 1;
1961 }
Tim Northover0d7bd4f2014-04-14 12:51:02 +00001962
1963 def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), CPSR),
1964 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
1965 (inv_cond_XFORM imm:$cond))>;
1966
1967 def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), CPSR),
1968 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
1969 (inv_cond_XFORM imm:$cond))>;
Tim Northover00ed9962014-03-29 10:18:08 +00001970}
1971
1972//---
1973// Special Mask Value
1974//---
1975def maski8_or_more : Operand<i32>,
1976 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1977}
1978def maski16_or_more : Operand<i32>,
1979 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
1980}
1981
1982
1983//---
1984// Load/store
1985//---
1986
1987// (unsigned immediate)
1988// Indexed for 8-bit registers. offset is in range [0,4095].
1989def MemoryIndexed8Operand : AsmOperandClass {
1990 let Name = "MemoryIndexed8";
1991 let DiagnosticType = "InvalidMemoryIndexed8";
1992}
1993def am_indexed8 : Operand<i64>,
1994 ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
1995 let PrintMethod = "printAMIndexed8";
1996 let EncoderMethod
1997 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
1998 let ParserMatchClass = MemoryIndexed8Operand;
1999 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2000}
2001
2002// Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
2003// stored as immval/2 (the 12-bit literal that encodes directly into the insn).
2004def MemoryIndexed16Operand : AsmOperandClass {
2005 let Name = "MemoryIndexed16";
2006 let DiagnosticType = "InvalidMemoryIndexed16";
2007}
2008def am_indexed16 : Operand<i64>,
2009 ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2010 let PrintMethod = "printAMIndexed16";
2011 let EncoderMethod
2012 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2013 let ParserMatchClass = MemoryIndexed16Operand;
2014 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2015}
2016
2017// Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2018// stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2019def MemoryIndexed32Operand : AsmOperandClass {
2020 let Name = "MemoryIndexed32";
2021 let DiagnosticType = "InvalidMemoryIndexed32";
2022}
2023def am_indexed32 : Operand<i64>,
2024 ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2025 let PrintMethod = "printAMIndexed32";
2026 let EncoderMethod
2027 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2028 let ParserMatchClass = MemoryIndexed32Operand;
2029 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2030}
2031
2032// Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2033// stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2034def MemoryIndexed64Operand : AsmOperandClass {
2035 let Name = "MemoryIndexed64";
2036 let DiagnosticType = "InvalidMemoryIndexed64";
2037}
2038def am_indexed64 : Operand<i64>,
2039 ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2040 let PrintMethod = "printAMIndexed64";
2041 let EncoderMethod
2042 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2043 let ParserMatchClass = MemoryIndexed64Operand;
2044 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2045}
2046
2047// Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2048// stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2049def MemoryIndexed128Operand : AsmOperandClass {
2050 let Name = "MemoryIndexed128";
2051 let DiagnosticType = "InvalidMemoryIndexed128";
2052}
2053def am_indexed128 : Operand<i64>,
2054 ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2055 let PrintMethod = "printAMIndexed128";
2056 let EncoderMethod
2057 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2058 let ParserMatchClass = MemoryIndexed128Operand;
2059 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2060}
2061
2062// No offset.
2063def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2064def am_noindex : Operand<i64>,
2065 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2066 let PrintMethod = "printAMNoIndex";
2067 let ParserMatchClass = MemoryNoIndexOperand;
2068 let MIOperandInfo = (ops GPR64sp:$base);
2069}
2070
2071class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2072 string asm, list<dag> pattern>
2073 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2074 bits<5> dst;
2075
2076 bits<17> addr;
2077 bits<5> base = addr{4-0};
2078 bits<12> offset = addr{16-5};
2079
2080 let Inst{31-30} = sz;
2081 let Inst{29-27} = 0b111;
2082 let Inst{26} = V;
2083 let Inst{25-24} = 0b01;
2084 let Inst{23-22} = opc;
2085 let Inst{21-10} = offset;
2086 let Inst{9-5} = base;
2087 let Inst{4-0} = dst;
2088
2089 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2090}
2091
2092let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2093class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2094 Operand indextype, string asm, list<dag> pattern>
2095 : BaseLoadStoreUI<sz, V, opc,
2096 (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2097 Sched<[WriteLD]>;
2098
2099let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2100class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2101 Operand indextype, string asm, list<dag> pattern>
2102 : BaseLoadStoreUI<sz, V, opc,
2103 (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2104 Sched<[WriteST]>;
2105
2106def PrefetchOperand : AsmOperandClass {
2107 let Name = "Prefetch";
2108 let ParserMethod = "tryParsePrefetch";
2109}
2110def prfop : Operand<i32> {
2111 let PrintMethod = "printPrefetchOp";
2112 let ParserMatchClass = PrefetchOperand;
2113}
2114
2115let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2116class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2117 : BaseLoadStoreUI<sz, V, opc,
2118 (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2119 Sched<[WriteLD]>;
2120
2121//---
2122// Load literal
2123//---
2124
2125let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2126class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2127 : I<(outs regtype:$Rt), (ins am_brcond:$label),
2128 asm, "\t$Rt, $label", "", []>,
2129 Sched<[WriteLD]> {
2130 bits<5> Rt;
2131 bits<19> label;
2132 let Inst{31-30} = opc;
2133 let Inst{29-27} = 0b011;
2134 let Inst{26} = V;
2135 let Inst{25-24} = 0b00;
2136 let Inst{23-5} = label;
2137 let Inst{4-0} = Rt;
2138}
2139
2140let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2141class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2142 : I<(outs), (ins prfop:$Rt, am_brcond:$label),
2143 asm, "\t$Rt, $label", "", pat>,
2144 Sched<[WriteLD]> {
2145 bits<5> Rt;
2146 bits<19> label;
2147 let Inst{31-30} = opc;
2148 let Inst{29-27} = 0b011;
2149 let Inst{26} = V;
2150 let Inst{25-24} = 0b00;
2151 let Inst{23-5} = label;
2152 let Inst{4-0} = Rt;
2153}
2154
2155//---
2156// Load/store register offset
2157//---
2158
2159class MemROAsmOperand<int sz> : AsmOperandClass {
2160 let Name = "MemoryRegisterOffset"#sz;
2161}
2162
2163def MemROAsmOperand8 : MemROAsmOperand<8>;
2164def MemROAsmOperand16 : MemROAsmOperand<16>;
2165def MemROAsmOperand32 : MemROAsmOperand<32>;
2166def MemROAsmOperand64 : MemROAsmOperand<64>;
2167def MemROAsmOperand128 : MemROAsmOperand<128>;
2168
2169class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2170 let PrintMethod = "printMemoryRegOffset"#sz;
2171 let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2172}
2173
2174def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2175 let ParserMatchClass = MemROAsmOperand8;
2176}
2177
2178def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2179 let ParserMatchClass = MemROAsmOperand16;
2180}
2181
2182def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2183 let ParserMatchClass = MemROAsmOperand32;
2184}
2185
2186def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2187 let ParserMatchClass = MemROAsmOperand64;
2188}
2189
2190def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2191 let ParserMatchClass = MemROAsmOperand128;
2192}
2193
2194class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2195 string asm, dag ins, dag outs, list<dag> pat>
2196 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2197 // The operands are in order to match the 'addr' MI operands, so we
2198 // don't need an encoder method and by-name matching. Just use the default
2199 // in-order handling. Since we're using by-order, make sure the names
2200 // do not match.
2201 bits<5> dst;
2202 bits<5> base;
2203 bits<5> offset;
2204 bits<4> extend;
2205 let Inst{31-30} = sz;
2206 let Inst{29-27} = 0b111;
2207 let Inst{26} = V;
2208 let Inst{25-24} = 0b00;
2209 let Inst{23-22} = opc;
2210 let Inst{21} = 1;
2211 let Inst{20-16} = offset;
2212 let Inst{15-13} = extend{3-1};
2213
2214 let Inst{12} = extend{0};
2215 let Inst{11-10} = 0b10;
2216 let Inst{9-5} = base;
2217 let Inst{4-0} = dst;
2218
2219 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2220}
2221
2222class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2223 string asm, list<dag> pat>
2224 : LoadStore8RO<sz, V, opc, regtype, asm,
2225 (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2226 Sched<[WriteLDIdx, ReadAdrBase]>;
2227
2228class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2229 string asm, list<dag> pat>
2230 : LoadStore8RO<sz, V, opc, regtype, asm,
2231 (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2232 Sched<[WriteSTIdx, ReadAdrBase]>;
2233
2234class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2235 string asm, dag ins, dag outs, list<dag> pat>
2236 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2237 // The operands are in order to match the 'addr' MI operands, so we
2238 // don't need an encoder method and by-name matching. Just use the default
2239 // in-order handling. Since we're using by-order, make sure the names
2240 // do not match.
2241 bits<5> dst;
2242 bits<5> base;
2243 bits<5> offset;
2244 bits<4> extend;
2245 let Inst{31-30} = sz;
2246 let Inst{29-27} = 0b111;
2247 let Inst{26} = V;
2248 let Inst{25-24} = 0b00;
2249 let Inst{23-22} = opc;
2250 let Inst{21} = 1;
2251 let Inst{20-16} = offset;
2252 let Inst{15-13} = extend{3-1};
2253
2254 let Inst{12} = extend{0};
2255 let Inst{11-10} = 0b10;
2256 let Inst{9-5} = base;
2257 let Inst{4-0} = dst;
2258
2259 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2260}
2261
2262class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2263 string asm, list<dag> pat>
2264 : LoadStore16RO<sz, V, opc, regtype, asm,
2265 (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2266 Sched<[WriteLDIdx, ReadAdrBase]>;
2267
2268class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2269 string asm, list<dag> pat>
2270 : LoadStore16RO<sz, V, opc, regtype, asm,
2271 (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2272 Sched<[WriteSTIdx, ReadAdrBase]>;
2273
2274class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2275 string asm, dag ins, dag outs, list<dag> pat>
2276 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2277 // The operands are in order to match the 'addr' MI operands, so we
2278 // don't need an encoder method and by-name matching. Just use the default
2279 // in-order handling. Since we're using by-order, make sure the names
2280 // do not match.
2281 bits<5> dst;
2282 bits<5> base;
2283 bits<5> offset;
2284 bits<4> extend;
2285 let Inst{31-30} = sz;
2286 let Inst{29-27} = 0b111;
2287 let Inst{26} = V;
2288 let Inst{25-24} = 0b00;
2289 let Inst{23-22} = opc;
2290 let Inst{21} = 1;
2291 let Inst{20-16} = offset;
2292 let Inst{15-13} = extend{3-1};
2293
2294 let Inst{12} = extend{0};
2295 let Inst{11-10} = 0b10;
2296 let Inst{9-5} = base;
2297 let Inst{4-0} = dst;
2298
2299 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2300}
2301
2302class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2303 string asm, list<dag> pat>
2304 : LoadStore32RO<sz, V, opc, regtype, asm,
2305 (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2306 Sched<[WriteLDIdx, ReadAdrBase]>;
2307
2308class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2309 string asm, list<dag> pat>
2310 : LoadStore32RO<sz, V, opc, regtype, asm,
2311 (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2312 Sched<[WriteSTIdx, ReadAdrBase]>;
2313
2314class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2315 string asm, dag ins, dag outs, list<dag> pat>
2316 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2317 // The operands are in order to match the 'addr' MI operands, so we
2318 // don't need an encoder method and by-name matching. Just use the default
2319 // in-order handling. Since we're using by-order, make sure the names
2320 // do not match.
2321 bits<5> dst;
2322 bits<5> base;
2323 bits<5> offset;
2324 bits<4> extend;
2325 let Inst{31-30} = sz;
2326 let Inst{29-27} = 0b111;
2327 let Inst{26} = V;
2328 let Inst{25-24} = 0b00;
2329 let Inst{23-22} = opc;
2330 let Inst{21} = 1;
2331 let Inst{20-16} = offset;
2332 let Inst{15-13} = extend{3-1};
2333
2334 let Inst{12} = extend{0};
2335 let Inst{11-10} = 0b10;
2336 let Inst{9-5} = base;
2337 let Inst{4-0} = dst;
2338
2339 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2340}
2341
2342let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2343class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2344 string asm, list<dag> pat>
2345 : LoadStore64RO<sz, V, opc, regtype, asm,
2346 (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2347 Sched<[WriteLDIdx, ReadAdrBase]>;
2348
2349let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2350class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2351 string asm, list<dag> pat>
2352 : LoadStore64RO<sz, V, opc, regtype, asm,
2353 (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2354 Sched<[WriteSTIdx, ReadAdrBase]>;
2355
2356
2357class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2358 string asm, dag ins, dag outs, list<dag> pat>
2359 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2360 // The operands are in order to match the 'addr' MI operands, so we
2361 // don't need an encoder method and by-name matching. Just use the default
2362 // in-order handling. Since we're using by-order, make sure the names
2363 // do not match.
2364 bits<5> dst;
2365 bits<5> base;
2366 bits<5> offset;
2367 bits<4> extend;
2368 let Inst{31-30} = sz;
2369 let Inst{29-27} = 0b111;
2370 let Inst{26} = V;
2371 let Inst{25-24} = 0b00;
2372 let Inst{23-22} = opc;
2373 let Inst{21} = 1;
2374 let Inst{20-16} = offset;
2375 let Inst{15-13} = extend{3-1};
2376
2377 let Inst{12} = extend{0};
2378 let Inst{11-10} = 0b10;
2379 let Inst{9-5} = base;
2380 let Inst{4-0} = dst;
2381
2382 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2383}
2384
2385let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2386class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2387 string asm, list<dag> pat>
2388 : LoadStore128RO<sz, V, opc, regtype, asm,
2389 (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2390 Sched<[WriteLDIdx, ReadAdrBase]>;
2391
2392let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2393class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2394 string asm, list<dag> pat>
2395 : LoadStore128RO<sz, V, opc, regtype, asm,
2396 (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2397 Sched<[WriteSTIdx, ReadAdrBase]>;
2398
2399let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2400class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2401 : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2402 "\t$Rt, $addr", "", pat>,
2403 Sched<[WriteLD]> {
2404 // The operands are in order to match the 'addr' MI operands, so we
2405 // don't need an encoder method and by-name matching. Just use the default
2406 // in-order handling. Since we're using by-order, make sure the names
2407 // do not match.
2408 bits<5> dst;
2409 bits<5> base;
2410 bits<5> offset;
2411 bits<4> extend;
2412 let Inst{31-30} = sz;
2413 let Inst{29-27} = 0b111;
2414 let Inst{26} = V;
2415 let Inst{25-24} = 0b00;
2416 let Inst{23-22} = opc;
2417 let Inst{21} = 1;
2418 let Inst{20-16} = offset;
2419 let Inst{15-13} = extend{3-1};
2420
2421 let Inst{12} = extend{0};
2422 let Inst{11-10} = 0b10;
2423 let Inst{9-5} = base;
2424 let Inst{4-0} = dst;
2425
2426 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2427}
2428
2429//---
2430// Load/store unscaled immediate
2431//---
2432
2433def MemoryUnscaledOperand : AsmOperandClass {
2434 let Name = "MemoryUnscaled";
2435 let DiagnosticType = "InvalidMemoryIndexedSImm9";
2436}
2437class am_unscaled_operand : Operand<i64> {
2438 let PrintMethod = "printAMUnscaled";
2439 let ParserMatchClass = MemoryUnscaledOperand;
2440 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2441}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002442class am_unscaled_wb_operand : Operand<i64> {
2443 let PrintMethod = "printAMUnscaledWB";
2444 let ParserMatchClass = MemoryUnscaledOperand;
2445 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2446}
Tim Northover00ed9962014-03-29 10:18:08 +00002447def am_unscaled : am_unscaled_operand;
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002448def am_unscaled_wb: am_unscaled_wb_operand;
Tim Northover00ed9962014-03-29 10:18:08 +00002449def am_unscaled8 : am_unscaled_operand,
2450 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2451def am_unscaled16 : am_unscaled_operand,
2452 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2453def am_unscaled32 : am_unscaled_operand,
2454 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2455def am_unscaled64 : am_unscaled_operand,
2456 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2457def am_unscaled128 : am_unscaled_operand,
2458 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2459
2460class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2461 string asm, list<dag> pattern>
2462 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2463 // The operands are in order to match the 'addr' MI operands, so we
2464 // don't need an encoder method and by-name matching. Just use the default
2465 // in-order handling. Since we're using by-order, make sure the names
2466 // do not match.
2467 bits<5> dst;
2468 bits<5> base;
2469 bits<9> offset;
2470 let Inst{31-30} = sz;
2471 let Inst{29-27} = 0b111;
2472 let Inst{26} = V;
2473 let Inst{25-24} = 0b00;
2474 let Inst{23-22} = opc;
2475 let Inst{21} = 0;
2476 let Inst{20-12} = offset;
2477 let Inst{11-10} = 0b00;
2478 let Inst{9-5} = base;
2479 let Inst{4-0} = dst;
2480
2481 let DecoderMethod = "DecodeSignedLdStInstruction";
2482}
2483
2484let AddedComplexity = 1 in // try this before LoadUI
2485class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2486 Operand amtype, string asm, list<dag> pattern>
2487 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2488 (ins amtype:$addr), asm, pattern>,
2489 Sched<[WriteLD]>;
2490
2491let AddedComplexity = 1 in // try this before StoreUI
2492class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2493 Operand amtype, string asm, list<dag> pattern>
2494 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2495 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2496 Sched<[WriteST]>;
2497
2498let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2499class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2500 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2501 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2502 Sched<[WriteLD]>;
2503
2504//---
2505// Load/store unscaled immediate, unprivileged
2506//---
2507
2508class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2509 dag oops, dag iops, string asm>
2510 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2511 // The operands are in order to match the 'addr' MI operands, so we
2512 // don't need an encoder method and by-name matching. Just use the default
2513 // in-order handling. Since we're using by-order, make sure the names
2514 // do not match.
2515 bits<5> dst;
2516 bits<5> base;
2517 bits<9> offset;
2518 let Inst{31-30} = sz;
2519 let Inst{29-27} = 0b111;
2520 let Inst{26} = V;
2521 let Inst{25-24} = 0b00;
2522 let Inst{23-22} = opc;
2523 let Inst{21} = 0;
2524 let Inst{20-12} = offset;
2525 let Inst{11-10} = 0b10;
2526 let Inst{9-5} = base;
2527 let Inst{4-0} = dst;
2528
2529 let DecoderMethod = "DecodeSignedLdStInstruction";
2530}
2531
2532let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2533class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2534 string asm>
2535 : BaseLoadStoreUnprivileged<sz, V, opc,
2536 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2537 Sched<[WriteLD]>;
2538}
2539
2540let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2541class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2542 string asm>
2543 : BaseLoadStoreUnprivileged<sz, V, opc,
2544 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2545 Sched<[WriteST]>;
2546}
2547
2548//---
2549// Load/store pre-indexed
2550//---
2551
2552class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2553 string asm, string cstr>
2554 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2555 // The operands are in order to match the 'addr' MI operands, so we
2556 // don't need an encoder method and by-name matching. Just use the default
2557 // in-order handling.
2558 bits<5> dst;
2559 bits<5> base;
2560 bits<9> offset;
2561 let Inst{31-30} = sz;
2562 let Inst{29-27} = 0b111;
2563 let Inst{26} = V;
2564 let Inst{25-24} = 0;
2565 let Inst{23-22} = opc;
2566 let Inst{21} = 0;
2567 let Inst{20-12} = offset;
2568 let Inst{11-10} = 0b11;
2569 let Inst{9-5} = base;
2570 let Inst{4-0} = dst;
2571
2572 let DecoderMethod = "DecodeSignedLdStInstruction";
2573}
2574
2575let hasSideEffects = 0 in {
2576let mayStore = 0, mayLoad = 1 in
2577// FIXME: Modeling the write-back of these instructions for isel is tricky.
2578// we need the complex addressing mode for the memory reference, but
2579// we also need the write-back specified as a tied operand to the
2580// base register. That combination does not play nicely with
2581// the asm matcher and friends.
2582class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2583 string asm>
2584 : BaseLoadStorePreIdx<sz, V, opc,
2585 (outs regtype:$Rt/*, GPR64sp:$wback*/),
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002586 (ins am_unscaled_wb:$addr), asm, ""/*"$addr.base = $wback"*/>,
Tim Northover00ed9962014-03-29 10:18:08 +00002587 Sched<[WriteLD, WriteAdr]>;
2588
2589let mayStore = 1, mayLoad = 0 in
2590class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2591 string asm>
2592 : BaseLoadStorePreIdx<sz, V, opc,
2593 (outs/* GPR64sp:$wback*/),
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002594 (ins regtype:$Rt, am_unscaled_wb:$addr),
Tim Northover00ed9962014-03-29 10:18:08 +00002595 asm, ""/*"$addr.base = $wback"*/>,
2596 Sched<[WriteAdr, WriteST]>;
2597} // hasSideEffects = 0
2598
2599// ISel pseudo-instructions which have the tied operands. When the MC lowering
2600// logic finally gets smart enough to strip off tied operands that are just
2601// for isel convenience, we can get rid of these pseudos and just reference
2602// the real instructions directly.
2603//
2604// Ironically, also because of the writeback operands, we can't put the
2605// matcher pattern directly on the instruction, but need to define it
2606// separately.
2607//
2608// Loads aren't matched with patterns here at all, but rather in C++
2609// custom lowering.
2610let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2611class LoadPreIdxPseudo<RegisterClass regtype>
2612 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2613 (ins am_noindex:$addr, simm9:$offset), [],
2614 "$addr.base = $wback,@earlyclobber $wback">,
2615 Sched<[WriteLD, WriteAdr]>;
2616class LoadPostIdxPseudo<RegisterClass regtype>
2617 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2618 (ins am_noindex:$addr, simm9:$offset), [],
2619 "$addr.base = $wback,@earlyclobber $wback">,
2620 Sched<[WriteLD, WriteI]>;
2621}
2622multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2623 SDPatternOperator OpNode> {
2624 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2625 def _isel: Pseudo<(outs GPR64sp:$wback),
2626 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2627 "$addr.base = $wback,@earlyclobber $wback">,
2628 Sched<[WriteAdr, WriteST]>;
2629
2630 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2631 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2632 simm9:$offset)>;
2633}
2634
2635//---
2636// Load/store post-indexed
2637//---
2638
2639// (pre-index) load/stores.
2640class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2641 string asm, string cstr>
2642 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2643 // The operands are in order to match the 'addr' MI operands, so we
2644 // don't need an encoder method and by-name matching. Just use the default
2645 // in-order handling.
2646 bits<5> dst;
2647 bits<5> base;
2648 bits<9> offset;
2649 let Inst{31-30} = sz;
2650 let Inst{29-27} = 0b111;
2651 let Inst{26} = V;
2652 let Inst{25-24} = 0b00;
2653 let Inst{23-22} = opc;
2654 let Inst{21} = 0b0;
2655 let Inst{20-12} = offset;
2656 let Inst{11-10} = 0b01;
2657 let Inst{9-5} = base;
2658 let Inst{4-0} = dst;
2659
2660 let DecoderMethod = "DecodeSignedLdStInstruction";
2661}
2662
2663let hasSideEffects = 0 in {
2664let mayStore = 0, mayLoad = 1 in
2665// FIXME: Modeling the write-back of these instructions for isel is tricky.
2666// we need the complex addressing mode for the memory reference, but
2667// we also need the write-back specified as a tied operand to the
2668// base register. That combination does not play nicely with
2669// the asm matcher and friends.
2670class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2671 string asm>
2672 : BaseLoadStorePostIdx<sz, V, opc,
2673 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2674 (ins am_noindex:$addr, simm9:$idx),
2675 asm, ""/*"$addr.base = $wback"*/>,
2676 Sched<[WriteLD, WriteI]>;
2677
2678let mayStore = 1, mayLoad = 0 in
2679class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2680 string asm>
2681 : BaseLoadStorePostIdx<sz, V, opc,
2682 (outs/* GPR64sp:$wback*/),
2683 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2684 asm, ""/*"$addr.base = $wback"*/>,
2685 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2686} // hasSideEffects = 0
2687
2688// ISel pseudo-instructions which have the tied operands. When the MC lowering
2689// logic finally gets smart enough to strip off tied operands that are just
2690// for isel convenience, we can get rid of these pseudos and just reference
2691// the real instructions directly.
2692//
2693// Ironically, also because of the writeback operands, we can't put the
2694// matcher pattern directly on the instruction, but need to define it
2695// separately.
2696multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2697 SDPatternOperator OpNode, Instruction Insn> {
2698 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2699 def _isel: Pseudo<(outs GPR64sp:$wback),
2700 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2701 "$addr.base = $wback,@earlyclobber $wback">,
2702 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2703 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2704
2705 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2706 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2707 simm9:$idx)>;
2708}
2709
2710//---
2711// Load/store pair
2712//---
2713
2714// (indexed, offset)
2715
2716class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2717 string asm>
2718 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2719 // The operands are in order to match the 'addr' MI operands, so we
2720 // don't need an encoder method and by-name matching. Just use the default
2721 // in-order handling. Since we're using by-order, make sure the names
2722 // do not match.
2723 bits<5> dst;
2724 bits<5> dst2;
2725 bits<5> base;
2726 bits<7> offset;
2727 let Inst{31-30} = opc;
2728 let Inst{29-27} = 0b101;
2729 let Inst{26} = V;
2730 let Inst{25-23} = 0b010;
2731 let Inst{22} = L;
2732 let Inst{21-15} = offset;
2733 let Inst{14-10} = dst2;
2734 let Inst{9-5} = base;
2735 let Inst{4-0} = dst;
2736
2737 let DecoderMethod = "DecodePairLdStInstruction";
2738}
2739
2740let hasSideEffects = 0 in {
2741let mayStore = 0, mayLoad = 1 in
2742class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2743 Operand indextype, string asm>
2744 : BaseLoadStorePairOffset<opc, V, 1,
2745 (outs regtype:$Rt, regtype:$Rt2),
2746 (ins indextype:$addr), asm>,
2747 Sched<[WriteLD, WriteLDHi]>;
2748
2749let mayLoad = 0, mayStore = 1 in
2750class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2751 Operand indextype, string asm>
2752 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2753 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2754 asm>,
2755 Sched<[WriteSTP]>;
2756} // hasSideEffects = 0
2757
2758// (pre-indexed)
2759
2760def MemoryIndexed32SImm7 : AsmOperandClass {
2761 let Name = "MemoryIndexed32SImm7";
2762 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2763}
2764def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2765 let PrintMethod = "printAMIndexed32";
2766 let ParserMatchClass = MemoryIndexed32SImm7;
2767 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2768}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002769def am_indexed32simm7_wb : Operand<i32> { // ComplexPattern<...>
2770 let PrintMethod = "printAMIndexed32WB";
2771 let ParserMatchClass = MemoryIndexed32SImm7;
2772 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2773}
Tim Northover00ed9962014-03-29 10:18:08 +00002774
2775def MemoryIndexed64SImm7 : AsmOperandClass {
2776 let Name = "MemoryIndexed64SImm7";
2777 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2778}
2779def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2780 let PrintMethod = "printAMIndexed64";
2781 let ParserMatchClass = MemoryIndexed64SImm7;
2782 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2783}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002784def am_indexed64simm7_wb : Operand<i32> { // ComplexPattern<...>
2785 let PrintMethod = "printAMIndexed64WB";
2786 let ParserMatchClass = MemoryIndexed64SImm7;
2787 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2788}
Tim Northover00ed9962014-03-29 10:18:08 +00002789
2790def MemoryIndexed128SImm7 : AsmOperandClass {
2791 let Name = "MemoryIndexed128SImm7";
2792 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2793}
2794def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2795 let PrintMethod = "printAMIndexed128";
2796 let ParserMatchClass = MemoryIndexed128SImm7;
2797 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2798}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002799def am_indexed128simm7_wb : Operand<i32> { // ComplexPattern<...>
2800 let PrintMethod = "printAMIndexed128WB";
2801 let ParserMatchClass = MemoryIndexed128SImm7;
2802 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2803}
Tim Northover00ed9962014-03-29 10:18:08 +00002804
2805class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2806 string asm>
2807 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2808 // The operands are in order to match the 'addr' MI operands, so we
2809 // don't need an encoder method and by-name matching. Just use the default
2810 // in-order handling. Since we're using by-order, make sure the names
2811 // do not match.
2812 bits<5> dst;
2813 bits<5> dst2;
2814 bits<5> base;
2815 bits<7> offset;
2816 let Inst{31-30} = opc;
2817 let Inst{29-27} = 0b101;
2818 let Inst{26} = V;
2819 let Inst{25-23} = 0b011;
2820 let Inst{22} = L;
2821 let Inst{21-15} = offset;
2822 let Inst{14-10} = dst2;
2823 let Inst{9-5} = base;
2824 let Inst{4-0} = dst;
2825
2826 let DecoderMethod = "DecodePairLdStInstruction";
2827}
2828
2829let hasSideEffects = 0 in {
2830let mayStore = 0, mayLoad = 1 in
2831class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2832 Operand addrmode, string asm>
2833 : BaseLoadStorePairPreIdx<opc, V, 1,
2834 (outs regtype:$Rt, regtype:$Rt2),
2835 (ins addrmode:$addr), asm>,
2836 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2837
2838let mayStore = 1, mayLoad = 0 in
2839class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2840 Operand addrmode, string asm>
2841 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2842 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2843 asm>,
2844 Sched<[WriteAdr, WriteSTP]>;
2845} // hasSideEffects = 0
2846
2847// (post-indexed)
2848
2849class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2850 string asm>
2851 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2852 // The operands are in order to match the 'addr' MI operands, so we
2853 // don't need an encoder method and by-name matching. Just use the default
2854 // in-order handling. Since we're using by-order, make sure the names
2855 // do not match.
2856 bits<5> dst;
2857 bits<5> dst2;
2858 bits<5> base;
2859 bits<7> offset;
2860 let Inst{31-30} = opc;
2861 let Inst{29-27} = 0b101;
2862 let Inst{26} = V;
2863 let Inst{25-23} = 0b001;
2864 let Inst{22} = L;
2865 let Inst{21-15} = offset;
2866 let Inst{14-10} = dst2;
2867 let Inst{9-5} = base;
2868 let Inst{4-0} = dst;
2869
2870 let DecoderMethod = "DecodePairLdStInstruction";
2871}
2872
2873let hasSideEffects = 0 in {
2874let mayStore = 0, mayLoad = 1 in
2875class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2876 Operand idxtype, string asm>
2877 : BaseLoadStorePairPostIdx<opc, V, 1,
2878 (outs regtype:$Rt, regtype:$Rt2),
2879 (ins am_noindex:$addr, idxtype:$idx), asm>,
2880 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2881
2882let mayStore = 1, mayLoad = 0 in
2883class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2884 Operand idxtype, string asm>
2885 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2886 (ins regtype:$Rt, regtype:$Rt2,
2887 am_noindex:$addr, idxtype:$idx),
2888 asm>,
2889 Sched<[WriteAdr, WriteSTP]>;
2890} // hasSideEffects = 0
2891
2892// (no-allocate)
2893
2894class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2895 string asm>
2896 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2897 // The operands are in order to match the 'addr' MI operands, so we
2898 // don't need an encoder method and by-name matching. Just use the default
2899 // in-order handling. Since we're using by-order, make sure the names
2900 // do not match.
2901 bits<5> dst;
2902 bits<5> dst2;
2903 bits<5> base;
2904 bits<7> offset;
2905 let Inst{31-30} = opc;
2906 let Inst{29-27} = 0b101;
2907 let Inst{26} = V;
2908 let Inst{25-23} = 0b000;
2909 let Inst{22} = L;
2910 let Inst{21-15} = offset;
2911 let Inst{14-10} = dst2;
2912 let Inst{9-5} = base;
2913 let Inst{4-0} = dst;
2914
2915 let DecoderMethod = "DecodePairLdStInstruction";
2916}
2917
2918let hasSideEffects = 0 in {
2919let mayStore = 0, mayLoad = 1 in
2920class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2921 Operand indextype, string asm>
2922 : BaseLoadStorePairNoAlloc<opc, V, 1,
2923 (outs regtype:$Rt, regtype:$Rt2),
2924 (ins indextype:$addr), asm>,
2925 Sched<[WriteLD, WriteLDHi]>;
2926
2927let mayStore = 1, mayLoad = 0 in
2928class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2929 Operand indextype, string asm>
2930 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2931 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2932 asm>,
2933 Sched<[WriteSTP]>;
2934} // hasSideEffects = 0
2935
2936//---
2937// Load/store exclusive
2938//---
2939
2940// True exclusive operations write to and/or read from the system's exclusive
2941// monitors, which as far as a compiler is concerned can be modelled as a
2942// random shared memory address. Hence LoadExclusive mayStore.
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002943//
2944// Since these instructions have the undefined register bits set to 1 in
2945// their canonical form, we need a post encoder method to set those bits
2946// to 1 when encoding these instructions. We do this using the
2947// fixLoadStoreExclusive function. This function has template parameters:
2948//
2949// fixLoadStoreExclusive<int hasRs, int hasRt2>
2950//
2951// hasRs indicates that the instruction uses the Rs field, so we won't set
2952// it to 1 (and the same for Rt2). We don't need template parameters for
2953// the other register fields since Rt and Rn are always used.
2954//
Tim Northover00ed9962014-03-29 10:18:08 +00002955let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2956class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2957 dag oops, dag iops, string asm, string operands>
2958 : I<oops, iops, asm, operands, "", []> {
2959 let Inst{31-30} = sz;
2960 let Inst{29-24} = 0b001000;
2961 let Inst{23} = o2;
2962 let Inst{22} = L;
2963 let Inst{21} = o1;
2964 let Inst{15} = o0;
2965
2966 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2967}
2968
2969// Neither Rs nor Rt2 operands.
2970class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2971 dag oops, dag iops, string asm, string operands>
2972 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2973 bits<5> reg;
2974 bits<5> base;
Tim Northover00ed9962014-03-29 10:18:08 +00002975 let Inst{9-5} = base;
2976 let Inst{4-0} = reg;
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002977
2978 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
Tim Northover00ed9962014-03-29 10:18:08 +00002979}
2980
2981// Simple load acquires don't set the exclusive monitor
2982let mayLoad = 1, mayStore = 0 in
2983class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2984 RegisterClass regtype, string asm>
2985 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2986 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2987 Sched<[WriteLD]>;
2988
2989class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2990 RegisterClass regtype, string asm>
2991 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2992 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2993 Sched<[WriteLD]>;
2994
2995class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2996 RegisterClass regtype, string asm>
2997 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2998 (outs regtype:$Rt, regtype:$Rt2),
2999 (ins am_noindex:$addr), asm,
3000 "\t$Rt, $Rt2, $addr">,
3001 Sched<[WriteLD, WriteLDHi]> {
3002 bits<5> dst1;
3003 bits<5> dst2;
3004 bits<5> base;
Tim Northover00ed9962014-03-29 10:18:08 +00003005 let Inst{14-10} = dst2;
3006 let Inst{9-5} = base;
3007 let Inst{4-0} = dst1;
Bradley Smithbc35b1f2014-04-09 14:43:01 +00003008
3009 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
Tim Northover00ed9962014-03-29 10:18:08 +00003010}
3011
3012// Simple store release operations do not check the exclusive monitor.
3013let mayLoad = 0, mayStore = 1 in
3014class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3015 RegisterClass regtype, string asm>
3016 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3017 (ins regtype:$Rt, am_noindex:$addr),
3018 asm, "\t$Rt, $addr">,
3019 Sched<[WriteST]>;
3020
3021let mayLoad = 1, mayStore = 1 in
3022class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3023 RegisterClass regtype, string asm>
3024 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3025 (ins regtype:$Rt, am_noindex:$addr),
3026 asm, "\t$Ws, $Rt, $addr">,
3027 Sched<[WriteSTX]> {
3028 bits<5> status;
3029 bits<5> reg;
3030 bits<5> base;
3031 let Inst{20-16} = status;
Tim Northover00ed9962014-03-29 10:18:08 +00003032 let Inst{9-5} = base;
3033 let Inst{4-0} = reg;
3034
3035 let Constraints = "@earlyclobber $Ws";
Bradley Smithbc35b1f2014-04-09 14:43:01 +00003036 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
Tim Northover00ed9962014-03-29 10:18:08 +00003037}
3038
3039class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3040 RegisterClass regtype, string asm>
3041 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3042 (outs GPR32:$Ws),
3043 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3044 asm, "\t$Ws, $Rt, $Rt2, $addr">,
3045 Sched<[WriteSTX]> {
3046 bits<5> status;
3047 bits<5> dst1;
3048 bits<5> dst2;
3049 bits<5> base;
3050 let Inst{20-16} = status;
3051 let Inst{14-10} = dst2;
3052 let Inst{9-5} = base;
3053 let Inst{4-0} = dst1;
3054
3055 let Constraints = "@earlyclobber $Ws";
3056}
3057
3058//---
3059// Exception generation
3060//---
3061
3062let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3063class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3064 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3065 Sched<[WriteSys]> {
3066 bits<16> imm;
3067 let Inst{31-24} = 0b11010100;
3068 let Inst{23-21} = op1;
3069 let Inst{20-5} = imm;
3070 let Inst{4-2} = 0b000;
3071 let Inst{1-0} = ll;
3072}
3073
3074//---
3075// Floating point to integer conversion
3076//---
3077
3078class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3079 RegisterClass srcType, RegisterClass dstType,
3080 string asm, list<dag> pattern>
3081 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3082 asm, "\t$Rd, $Rn", "", pattern>,
3083 Sched<[WriteFCvt]> {
3084 bits<5> Rd;
3085 bits<5> Rn;
Bradley Smith0243aa32014-04-09 14:43:20 +00003086 let Inst{30-29} = 0b00;
Tim Northover00ed9962014-03-29 10:18:08 +00003087 let Inst{28-24} = 0b11110;
3088 let Inst{23-22} = type;
3089 let Inst{21} = 1;
3090 let Inst{20-19} = rmode;
3091 let Inst{18-16} = opcode;
3092 let Inst{15-10} = 0;
3093 let Inst{9-5} = Rn;
3094 let Inst{4-0} = Rd;
3095}
3096
3097let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3098class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3099 RegisterClass srcType, RegisterClass dstType,
Tim Northover80a70a22014-04-15 13:59:57 +00003100 Operand immType, string asm, list<dag> pattern>
Tim Northover00ed9962014-03-29 10:18:08 +00003101 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
Tim Northover80a70a22014-04-15 13:59:57 +00003102 asm, "\t$Rd, $Rn, $scale", "", pattern>,
Tim Northover00ed9962014-03-29 10:18:08 +00003103 Sched<[WriteFCvt]> {
3104 bits<5> Rd;
3105 bits<5> Rn;
3106 bits<6> scale;
Bradley Smith60e76672014-04-09 14:43:27 +00003107 let Inst{30-29} = 0b00;
Tim Northover00ed9962014-03-29 10:18:08 +00003108 let Inst{28-24} = 0b11110;
3109 let Inst{23-22} = type;
3110 let Inst{21} = 0;
3111 let Inst{20-19} = rmode;
3112 let Inst{18-16} = opcode;
3113 let Inst{15-10} = scale;
3114 let Inst{9-5} = Rn;
3115 let Inst{4-0} = Rd;
3116}
3117
Bradley Smith0243aa32014-04-09 14:43:20 +00003118multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3119 SDPatternOperator OpN> {
Tim Northover00ed9962014-03-29 10:18:08 +00003120 // Unscaled single-precision to 32-bit
3121 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3122 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3123 let Inst{31} = 0; // 32-bit GPR flag
3124 }
3125
3126 // Unscaled single-precision to 64-bit
3127 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3128 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3129 let Inst{31} = 1; // 64-bit GPR flag
3130 }
3131
3132 // Unscaled double-precision to 32-bit
3133 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3134 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3135 let Inst{31} = 0; // 32-bit GPR flag
3136 }
3137
3138 // Unscaled double-precision to 64-bit
3139 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3140 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3141 let Inst{31} = 1; // 64-bit GPR flag
3142 }
Bradley Smith0243aa32014-04-09 14:43:20 +00003143}
Tim Northover00ed9962014-03-29 10:18:08 +00003144
Bradley Smith0243aa32014-04-09 14:43:20 +00003145multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
Tim Northover80a70a22014-04-15 13:59:57 +00003146 SDPatternOperator OpN> {
Tim Northover00ed9962014-03-29 10:18:08 +00003147 // Scaled single-precision to 32-bit
3148 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
Tim Northover80a70a22014-04-15 13:59:57 +00003149 fixedpoint_f32_i32, asm,
3150 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3151 fixedpoint_f32_i32:$scale)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003152 let Inst{31} = 0; // 32-bit GPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003153 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003154 }
3155
3156 // Scaled single-precision to 64-bit
3157 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
Tim Northover80a70a22014-04-15 13:59:57 +00003158 fixedpoint_f32_i64, asm,
3159 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3160 fixedpoint_f32_i64:$scale)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003161 let Inst{31} = 1; // 64-bit GPR flag
3162 }
3163
3164 // Scaled double-precision to 32-bit
3165 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
Tim Northover80a70a22014-04-15 13:59:57 +00003166 fixedpoint_f64_i32, asm,
3167 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3168 fixedpoint_f64_i32:$scale)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003169 let Inst{31} = 0; // 32-bit GPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003170 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003171 }
3172
3173 // Scaled double-precision to 64-bit
3174 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
Tim Northover80a70a22014-04-15 13:59:57 +00003175 fixedpoint_f64_i64, asm,
3176 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3177 fixedpoint_f64_i64:$scale)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003178 let Inst{31} = 1; // 64-bit GPR flag
3179 }
3180}
3181
3182//---
3183// Integer to floating point conversion
3184//---
3185
3186let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3187class BaseIntegerToFP<bit isUnsigned,
3188 RegisterClass srcType, RegisterClass dstType,
Tim Northover80a70a22014-04-15 13:59:57 +00003189 Operand immType, string asm, list<dag> pattern>
Tim Northover00ed9962014-03-29 10:18:08 +00003190 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
Tim Northover80a70a22014-04-15 13:59:57 +00003191 asm, "\t$Rd, $Rn, $scale", "", pattern>,
Tim Northover00ed9962014-03-29 10:18:08 +00003192 Sched<[WriteFCvt]> {
3193 bits<5> Rd;
3194 bits<5> Rn;
3195 bits<6> scale;
3196 let Inst{30-23} = 0b00111100;
3197 let Inst{21-17} = 0b00001;
3198 let Inst{16} = isUnsigned;
3199 let Inst{15-10} = scale;
3200 let Inst{9-5} = Rn;
3201 let Inst{4-0} = Rd;
3202}
3203
3204class BaseIntegerToFPUnscaled<bit isUnsigned,
3205 RegisterClass srcType, RegisterClass dstType,
3206 ValueType dvt, string asm, SDNode node>
3207 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3208 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3209 Sched<[WriteFCvt]> {
3210 bits<5> Rd;
3211 bits<5> Rn;
3212 bits<6> scale;
3213 let Inst{30-23} = 0b00111100;
3214 let Inst{21-17} = 0b10001;
3215 let Inst{16} = isUnsigned;
3216 let Inst{15-10} = 0b000000;
3217 let Inst{9-5} = Rn;
3218 let Inst{4-0} = Rd;
3219}
3220
3221multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3222 // Unscaled
3223 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3224 let Inst{31} = 0; // 32-bit GPR flag
3225 let Inst{22} = 0; // 32-bit FPR flag
3226 }
3227
3228 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3229 let Inst{31} = 0; // 32-bit GPR flag
3230 let Inst{22} = 1; // 64-bit FPR flag
3231 }
3232
3233 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3234 let Inst{31} = 1; // 64-bit GPR flag
3235 let Inst{22} = 0; // 32-bit FPR flag
3236 }
3237
3238 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3239 let Inst{31} = 1; // 64-bit GPR flag
3240 let Inst{22} = 1; // 64-bit FPR flag
3241 }
3242
3243 // Scaled
Tim Northover80a70a22014-04-15 13:59:57 +00003244 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3245 [(set FPR32:$Rd,
3246 (fdiv (node GPR32:$Rn),
3247 fixedpoint_f32_i32:$scale))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003248 let Inst{31} = 0; // 32-bit GPR flag
3249 let Inst{22} = 0; // 32-bit FPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003250 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003251 }
3252
Tim Northover80a70a22014-04-15 13:59:57 +00003253 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3254 [(set FPR64:$Rd,
3255 (fdiv (node GPR32:$Rn),
3256 fixedpoint_f64_i32:$scale))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003257 let Inst{31} = 0; // 32-bit GPR flag
3258 let Inst{22} = 1; // 64-bit FPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003259 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003260 }
3261
Tim Northover80a70a22014-04-15 13:59:57 +00003262 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3263 [(set FPR32:$Rd,
3264 (fdiv (node GPR64:$Rn),
3265 fixedpoint_f32_i64:$scale))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003266 let Inst{31} = 1; // 64-bit GPR flag
3267 let Inst{22} = 0; // 32-bit FPR flag
3268 }
3269
Tim Northover80a70a22014-04-15 13:59:57 +00003270 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3271 [(set FPR64:$Rd,
3272 (fdiv (node GPR64:$Rn),
3273 fixedpoint_f64_i64:$scale))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00003274 let Inst{31} = 1; // 64-bit GPR flag
3275 let Inst{22} = 1; // 64-bit FPR flag
3276 }
3277}
3278
3279//---
3280// Unscaled integer <-> floating point conversion (i.e. FMOV)
3281//---
3282
3283let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3284class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3285 RegisterClass srcType, RegisterClass dstType,
3286 string asm>
3287 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3288 // We use COPY_TO_REGCLASS for these bitconvert operations.
3289 // copyPhysReg() expands the resultant COPY instructions after
3290 // regalloc is done. This gives greater freedom for the allocator
3291 // and related passes (coalescing, copy propagation, et. al.) to
3292 // be more effective.
3293 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3294 Sched<[WriteFCopy]> {
3295 bits<5> Rd;
3296 bits<5> Rn;
3297 let Inst{30-23} = 0b00111100;
3298 let Inst{21} = 1;
3299 let Inst{20-19} = rmode;
3300 let Inst{18-16} = opcode;
3301 let Inst{15-10} = 0b000000;
3302 let Inst{9-5} = Rn;
3303 let Inst{4-0} = Rd;
3304}
3305
3306let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3307class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
Bradley Smith239120c2014-04-09 14:44:49 +00003308 RegisterClass srcType, RegisterOperand dstType, string asm,
3309 string kind>
3310 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3311 "{\t$Rd"#kind#"[1], $Rn|"#kind#"\t$Rd[1], $Rn}", "", []>,
Tim Northover00ed9962014-03-29 10:18:08 +00003312 Sched<[WriteFCopy]> {
3313 bits<5> Rd;
3314 bits<5> Rn;
3315 let Inst{30-23} = 0b00111101;
3316 let Inst{21} = 1;
3317 let Inst{20-19} = rmode;
3318 let Inst{18-16} = opcode;
3319 let Inst{15-10} = 0b000000;
3320 let Inst{9-5} = Rn;
3321 let Inst{4-0} = Rd;
3322}
3323
3324let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3325class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
Bradley Smith239120c2014-04-09 14:44:49 +00003326 RegisterOperand srcType, RegisterClass dstType, string asm,
3327 string kind>
3328 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3329 "{\t$Rd, $Rn"#kind#"[1]|"#kind#"\t$Rd, $Rn[1]}", "", []>,
Tim Northover00ed9962014-03-29 10:18:08 +00003330 Sched<[WriteFCopy]> {
3331 bits<5> Rd;
3332 bits<5> Rn;
3333 let Inst{30-23} = 0b00111101;
3334 let Inst{21} = 1;
3335 let Inst{20-19} = rmode;
3336 let Inst{18-16} = opcode;
3337 let Inst{15-10} = 0b000000;
3338 let Inst{9-5} = Rn;
3339 let Inst{4-0} = Rd;
3340}
3341
3342
3343
3344multiclass UnscaledConversion<string asm> {
3345 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3346 let Inst{31} = 0; // 32-bit GPR flag
3347 let Inst{22} = 0; // 32-bit FPR flag
3348 }
3349
3350 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3351 let Inst{31} = 1; // 64-bit GPR flag
3352 let Inst{22} = 1; // 64-bit FPR flag
3353 }
3354
3355 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3356 let Inst{31} = 0; // 32-bit GPR flag
3357 let Inst{22} = 0; // 32-bit FPR flag
3358 }
3359
3360 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3361 let Inst{31} = 1; // 64-bit GPR flag
3362 let Inst{22} = 1; // 64-bit FPR flag
3363 }
3364
3365 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
Bradley Smith239120c2014-04-09 14:44:49 +00003366 asm, ".d"> {
Tim Northover00ed9962014-03-29 10:18:08 +00003367 let Inst{31} = 1;
3368 let Inst{22} = 0;
3369 }
3370
3371 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
Bradley Smith239120c2014-04-09 14:44:49 +00003372 asm, ".d"> {
Tim Northover00ed9962014-03-29 10:18:08 +00003373 let Inst{31} = 1;
3374 let Inst{22} = 0;
3375 }
Tim Northover00ed9962014-03-29 10:18:08 +00003376}
3377
3378//---
3379// Floating point conversion
3380//---
3381
3382class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3383 RegisterClass srcType, string asm, list<dag> pattern>
3384 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3385 Sched<[WriteFCvt]> {
3386 bits<5> Rd;
3387 bits<5> Rn;
3388 let Inst{31-24} = 0b00011110;
3389 let Inst{23-22} = type;
3390 let Inst{21-17} = 0b10001;
3391 let Inst{16-15} = opcode;
3392 let Inst{14-10} = 0b10000;
3393 let Inst{9-5} = Rn;
3394 let Inst{4-0} = Rd;
3395}
3396
3397multiclass FPConversion<string asm> {
3398 // Double-precision to Half-precision
Tim Northoverb37cff12014-04-15 14:00:03 +00003399 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3400 [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
Tim Northover00ed9962014-03-29 10:18:08 +00003401
3402 // Double-precision to Single-precision
3403 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3404 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3405
3406 // Half-precision to Double-precision
Tim Northoverb37cff12014-04-15 14:00:03 +00003407 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3408 [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
Tim Northover00ed9962014-03-29 10:18:08 +00003409
3410 // Half-precision to Single-precision
Tim Northoverb37cff12014-04-15 14:00:03 +00003411 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3412 [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
Tim Northover00ed9962014-03-29 10:18:08 +00003413
3414 // Single-precision to Double-precision
3415 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3416 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3417
3418 // Single-precision to Half-precision
Tim Northoverb37cff12014-04-15 14:00:03 +00003419 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3420 [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
Tim Northover00ed9962014-03-29 10:18:08 +00003421}
3422
3423//---
3424// Single operand floating point data processing
3425//---
3426
3427let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3428class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3429 ValueType vt, string asm, SDPatternOperator node>
3430 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3431 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3432 Sched<[WriteF]> {
3433 bits<5> Rd;
3434 bits<5> Rn;
3435 let Inst{31-23} = 0b000111100;
3436 let Inst{21-19} = 0b100;
3437 let Inst{18-15} = opcode;
3438 let Inst{14-10} = 0b10000;
3439 let Inst{9-5} = Rn;
3440 let Inst{4-0} = Rd;
3441}
3442
3443multiclass SingleOperandFPData<bits<4> opcode, string asm,
3444 SDPatternOperator node = null_frag> {
3445 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3446 let Inst{22} = 0; // 32-bit size flag
3447 }
3448
3449 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3450 let Inst{22} = 1; // 64-bit size flag
3451 }
3452}
3453
3454//---
3455// Two operand floating point data processing
3456//---
3457
3458let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3459class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3460 string asm, list<dag> pat>
3461 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3462 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3463 Sched<[WriteF]> {
3464 bits<5> Rd;
3465 bits<5> Rn;
3466 bits<5> Rm;
3467 let Inst{31-23} = 0b000111100;
3468 let Inst{21} = 1;
3469 let Inst{20-16} = Rm;
3470 let Inst{15-12} = opcode;
3471 let Inst{11-10} = 0b10;
3472 let Inst{9-5} = Rn;
3473 let Inst{4-0} = Rd;
3474}
3475
3476multiclass TwoOperandFPData<bits<4> opcode, string asm,
3477 SDPatternOperator node = null_frag> {
3478 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3479 [(set (f32 FPR32:$Rd),
3480 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3481 let Inst{22} = 0; // 32-bit size flag
3482 }
3483
3484 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3485 [(set (f64 FPR64:$Rd),
3486 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3487 let Inst{22} = 1; // 64-bit size flag
3488 }
3489}
3490
3491multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3492 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3493 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3494 let Inst{22} = 0; // 32-bit size flag
3495 }
3496
3497 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3498 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3499 let Inst{22} = 1; // 64-bit size flag
3500 }
3501}
3502
3503
3504//---
3505// Three operand floating point data processing
3506//---
3507
3508class BaseThreeOperandFPData<bit isNegated, bit isSub,
3509 RegisterClass regtype, string asm, list<dag> pat>
3510 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3511 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3512 Sched<[WriteFMul]> {
3513 bits<5> Rd;
3514 bits<5> Rn;
3515 bits<5> Rm;
3516 bits<5> Ra;
3517 let Inst{31-23} = 0b000111110;
3518 let Inst{21} = isNegated;
3519 let Inst{20-16} = Rm;
3520 let Inst{15} = isSub;
3521 let Inst{14-10} = Ra;
3522 let Inst{9-5} = Rn;
3523 let Inst{4-0} = Rd;
3524}
3525
3526multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3527 SDPatternOperator node> {
3528 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3529 [(set FPR32:$Rd,
3530 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3531 let Inst{22} = 0; // 32-bit size flag
3532 }
3533
3534 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3535 [(set FPR64:$Rd,
3536 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3537 let Inst{22} = 1; // 64-bit size flag
3538 }
3539}
3540
3541//---
3542// Floating point data comparisons
3543//---
3544
3545let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3546class BaseOneOperandFPComparison<bit signalAllNans,
3547 RegisterClass regtype, string asm,
3548 list<dag> pat>
3549 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3550 Sched<[WriteFCmp]> {
3551 bits<5> Rn;
3552 let Inst{31-23} = 0b000111100;
3553 let Inst{21} = 1;
3554
Tim Northover00ed9962014-03-29 10:18:08 +00003555 let Inst{15-10} = 0b001000;
3556 let Inst{9-5} = Rn;
3557 let Inst{4} = signalAllNans;
3558 let Inst{3-0} = 0b1000;
Bradley Smith5511f082014-04-09 14:43:40 +00003559
3560 // Rm should be 0b00000 canonically, but we need to accept any value.
3561 let PostEncoderMethod = "fixOneOperandFPComparison";
Tim Northover00ed9962014-03-29 10:18:08 +00003562}
3563
3564let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3565class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3566 string asm, list<dag> pat>
3567 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3568 Sched<[WriteFCmp]> {
3569 bits<5> Rm;
3570 bits<5> Rn;
3571 let Inst{31-23} = 0b000111100;
3572 let Inst{21} = 1;
3573 let Inst{20-16} = Rm;
3574 let Inst{15-10} = 0b001000;
3575 let Inst{9-5} = Rn;
3576 let Inst{4} = signalAllNans;
3577 let Inst{3-0} = 0b0000;
3578}
3579
3580multiclass FPComparison<bit signalAllNans, string asm,
3581 SDPatternOperator OpNode = null_frag> {
3582 let Defs = [CPSR] in {
3583 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3584 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3585 let Inst{22} = 0;
3586 }
3587
3588 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3589 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3590 let Inst{22} = 0;
3591 }
3592
3593 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3594 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3595 let Inst{22} = 1;
3596 }
3597
3598 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3599 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3600 let Inst{22} = 1;
3601 }
3602 } // Defs = [CPSR]
3603}
3604
3605//---
3606// Floating point conditional comparisons
3607//---
3608
3609let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3610class BaseFPCondComparison<bit signalAllNans,
3611 RegisterClass regtype, string asm>
3612 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3613 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3614 Sched<[WriteFCmp]> {
3615 bits<5> Rn;
3616 bits<5> Rm;
3617 bits<4> nzcv;
3618 bits<4> cond;
3619
3620 let Inst{31-23} = 0b000111100;
3621 let Inst{21} = 1;
3622 let Inst{20-16} = Rm;
3623 let Inst{15-12} = cond;
3624 let Inst{11-10} = 0b01;
3625 let Inst{9-5} = Rn;
3626 let Inst{4} = signalAllNans;
3627 let Inst{3-0} = nzcv;
3628}
3629
3630multiclass FPCondComparison<bit signalAllNans, string asm> {
3631 let Defs = [CPSR], Uses = [CPSR] in {
3632 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3633 let Inst{22} = 0;
3634 }
3635
3636 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3637 let Inst{22} = 1;
3638 }
3639 } // Defs = [CPSR], Uses = [CPSR]
3640}
3641
3642//---
3643// Floating point conditional select
3644//---
3645
3646class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3647 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3648 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3649 [(set regtype:$Rd,
3650 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3651 (i32 imm:$cond), CPSR))]>,
3652 Sched<[WriteF]> {
3653 bits<5> Rd;
3654 bits<5> Rn;
3655 bits<5> Rm;
3656 bits<4> cond;
3657
3658 let Inst{31-23} = 0b000111100;
3659 let Inst{21} = 1;
3660 let Inst{20-16} = Rm;
3661 let Inst{15-12} = cond;
3662 let Inst{11-10} = 0b11;
3663 let Inst{9-5} = Rn;
3664 let Inst{4-0} = Rd;
3665}
3666
3667multiclass FPCondSelect<string asm> {
3668 let Uses = [CPSR] in {
3669 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3670 let Inst{22} = 0;
3671 }
3672
3673 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3674 let Inst{22} = 1;
3675 }
3676 } // Uses = [CPSR]
3677}
3678
3679//---
3680// Floating move immediate
3681//---
3682
3683class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3684 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3685 [(set regtype:$Rd, fpimmtype:$imm)]>,
3686 Sched<[WriteFImm]> {
3687 bits<5> Rd;
3688 bits<8> imm;
3689 let Inst{31-23} = 0b000111100;
3690 let Inst{21} = 1;
3691 let Inst{20-13} = imm;
3692 let Inst{12-5} = 0b10000000;
3693 let Inst{4-0} = Rd;
3694}
3695
3696multiclass FPMoveImmediate<string asm> {
3697 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3698 let Inst{22} = 0;
3699 }
3700
3701 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3702 let Inst{22} = 1;
3703 }
3704}
3705
3706//----------------------------------------------------------------------------
3707// AdvSIMD
3708//----------------------------------------------------------------------------
3709
3710def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3711def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3712def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3713def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3714def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3715 return ((uint64_t)Imm) < 16;
3716}]> {
3717 let ParserMatchClass = VectorIndexBOperand;
3718 let PrintMethod = "printVectorIndex";
3719 let MIOperandInfo = (ops i64imm);
3720}
3721def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3722 return ((uint64_t)Imm) < 8;
3723}]> {
3724 let ParserMatchClass = VectorIndexHOperand;
3725 let PrintMethod = "printVectorIndex";
3726 let MIOperandInfo = (ops i64imm);
3727}
3728def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3729 return ((uint64_t)Imm) < 4;
3730}]> {
3731 let ParserMatchClass = VectorIndexSOperand;
3732 let PrintMethod = "printVectorIndex";
3733 let MIOperandInfo = (ops i64imm);
3734}
3735def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3736 return ((uint64_t)Imm) < 2;
3737}]> {
3738 let ParserMatchClass = VectorIndexDOperand;
3739 let PrintMethod = "printVectorIndex";
3740 let MIOperandInfo = (ops i64imm);
3741}
3742
3743//----------------------------------------------------------------------------
3744// AdvSIMD three register vector instructions
3745//----------------------------------------------------------------------------
3746
3747let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3748class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3749 RegisterOperand regtype, string asm, string kind,
3750 list<dag> pattern>
3751 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3752 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3753 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3754 Sched<[WriteV]> {
3755 bits<5> Rd;
3756 bits<5> Rn;
3757 bits<5> Rm;
3758 let Inst{31} = 0;
3759 let Inst{30} = Q;
3760 let Inst{29} = U;
3761 let Inst{28-24} = 0b01110;
3762 let Inst{23-22} = size;
3763 let Inst{21} = 1;
3764 let Inst{20-16} = Rm;
3765 let Inst{15-11} = opcode;
3766 let Inst{10} = 1;
3767 let Inst{9-5} = Rn;
3768 let Inst{4-0} = Rd;
3769}
3770
3771let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3772class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3773 RegisterOperand regtype, string asm, string kind,
3774 list<dag> pattern>
3775 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3776 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3777 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3778 Sched<[WriteV]> {
3779 bits<5> Rd;
3780 bits<5> Rn;
3781 bits<5> Rm;
3782 let Inst{31} = 0;
3783 let Inst{30} = Q;
3784 let Inst{29} = U;
3785 let Inst{28-24} = 0b01110;
3786 let Inst{23-22} = size;
3787 let Inst{21} = 1;
3788 let Inst{20-16} = Rm;
3789 let Inst{15-11} = opcode;
3790 let Inst{10} = 1;
3791 let Inst{9-5} = Rn;
3792 let Inst{4-0} = Rd;
3793}
3794
3795// All operand sizes distinguished in the encoding.
3796multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3797 SDPatternOperator OpNode> {
3798 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3799 asm, ".8b",
3800 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3801 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3802 asm, ".16b",
3803 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3804 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3805 asm, ".4h",
3806 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3807 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3808 asm, ".8h",
3809 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3810 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3811 asm, ".2s",
3812 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3813 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3814 asm, ".4s",
3815 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3816 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3817 asm, ".2d",
3818 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3819}
3820
3821// As above, but D sized elements unsupported.
3822multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3823 SDPatternOperator OpNode> {
3824 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3825 asm, ".8b",
3826 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3827 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3828 asm, ".16b",
3829 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3830 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3831 asm, ".4h",
3832 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3833 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3834 asm, ".8h",
3835 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3836 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3837 asm, ".2s",
3838 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3839 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3840 asm, ".4s",
3841 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3842}
3843
3844multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3845 SDPatternOperator OpNode> {
3846 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3847 asm, ".8b",
3848 [(set (v8i8 V64:$dst),
3849 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3850 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3851 asm, ".16b",
3852 [(set (v16i8 V128:$dst),
3853 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3854 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3855 asm, ".4h",
3856 [(set (v4i16 V64:$dst),
3857 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3858 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3859 asm, ".8h",
3860 [(set (v8i16 V128:$dst),
3861 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3862 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3863 asm, ".2s",
3864 [(set (v2i32 V64:$dst),
3865 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3866 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3867 asm, ".4s",
3868 [(set (v4i32 V128:$dst),
3869 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3870}
3871
3872// As above, but only B sized elements supported.
3873multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3874 SDPatternOperator OpNode> {
3875 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3876 asm, ".8b",
3877 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3878 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3879 asm, ".16b",
3880 [(set (v16i8 V128:$Rd),
3881 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3882}
3883
3884// As above, but only S and D sized floating point elements supported.
3885multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3886 string asm, SDPatternOperator OpNode> {
3887 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3888 asm, ".2s",
3889 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3890 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3891 asm, ".4s",
3892 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3893 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3894 asm, ".2d",
3895 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3896}
3897
3898multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3899 string asm,
3900 SDPatternOperator OpNode> {
3901 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3902 asm, ".2s",
3903 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3904 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3905 asm, ".4s",
3906 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3907 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3908 asm, ".2d",
3909 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3910}
3911
3912multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3913 string asm, SDPatternOperator OpNode> {
3914 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3915 asm, ".2s",
3916 [(set (v2f32 V64:$dst),
3917 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3918 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3919 asm, ".4s",
3920 [(set (v4f32 V128:$dst),
3921 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3922 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3923 asm, ".2d",
3924 [(set (v2f64 V128:$dst),
3925 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3926}
3927
3928// As above, but D and B sized elements unsupported.
3929multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3930 SDPatternOperator OpNode> {
3931 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3932 asm, ".4h",
3933 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3934 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3935 asm, ".8h",
3936 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3937 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3938 asm, ".2s",
3939 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3940 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3941 asm, ".4s",
3942 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3943}
3944
3945// Logical three vector ops share opcode bits, and only use B sized elements.
3946multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3947 SDPatternOperator OpNode = null_frag> {
3948 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3949 asm, ".8b",
3950 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3951 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3952 asm, ".16b",
3953 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3954
3955 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3956 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3957 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3958 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3959 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3960 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3961
3962 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3963 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3964 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3965 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3966 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3967 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3968}
3969
3970multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3971 string asm, SDPatternOperator OpNode> {
3972 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3973 asm, ".8b",
3974 [(set (v8i8 V64:$dst),
3975 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3976 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3977 asm, ".16b",
3978 [(set (v16i8 V128:$dst),
3979 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3980 (v16i8 V128:$Rm)))]>;
3981
3982 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3983 (v4i16 V64:$RHS))),
3984 (!cast<Instruction>(NAME#"v8i8")
3985 V64:$LHS, V64:$MHS, V64:$RHS)>;
3986 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3987 (v2i32 V64:$RHS))),
3988 (!cast<Instruction>(NAME#"v8i8")
3989 V64:$LHS, V64:$MHS, V64:$RHS)>;
3990 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3991 (v1i64 V64:$RHS))),
3992 (!cast<Instruction>(NAME#"v8i8")
3993 V64:$LHS, V64:$MHS, V64:$RHS)>;
3994
3995 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3996 (v8i16 V128:$RHS))),
3997 (!cast<Instruction>(NAME#"v16i8")
3998 V128:$LHS, V128:$MHS, V128:$RHS)>;
3999 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4000 (v4i32 V128:$RHS))),
4001 (!cast<Instruction>(NAME#"v16i8")
4002 V128:$LHS, V128:$MHS, V128:$RHS)>;
4003 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4004 (v2i64 V128:$RHS))),
4005 (!cast<Instruction>(NAME#"v16i8")
4006 V128:$LHS, V128:$MHS, V128:$RHS)>;
4007}
4008
4009
4010//----------------------------------------------------------------------------
4011// AdvSIMD two register vector instructions.
4012//----------------------------------------------------------------------------
4013
4014let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4015class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4016 RegisterOperand regtype, string asm, string dstkind,
4017 string srckind, list<dag> pattern>
4018 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4019 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4020 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4021 Sched<[WriteV]> {
4022 bits<5> Rd;
4023 bits<5> Rn;
4024 let Inst{31} = 0;
4025 let Inst{30} = Q;
4026 let Inst{29} = U;
4027 let Inst{28-24} = 0b01110;
4028 let Inst{23-22} = size;
4029 let Inst{21-17} = 0b10000;
4030 let Inst{16-12} = opcode;
4031 let Inst{11-10} = 0b10;
4032 let Inst{9-5} = Rn;
4033 let Inst{4-0} = Rd;
4034}
4035
4036let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4037class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4038 RegisterOperand regtype, string asm, string dstkind,
4039 string srckind, list<dag> pattern>
4040 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4041 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4042 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4043 Sched<[WriteV]> {
4044 bits<5> Rd;
4045 bits<5> Rn;
4046 let Inst{31} = 0;
4047 let Inst{30} = Q;
4048 let Inst{29} = U;
4049 let Inst{28-24} = 0b01110;
4050 let Inst{23-22} = size;
4051 let Inst{21-17} = 0b10000;
4052 let Inst{16-12} = opcode;
4053 let Inst{11-10} = 0b10;
4054 let Inst{9-5} = Rn;
4055 let Inst{4-0} = Rd;
4056}
4057
4058// Supports B, H, and S element sizes.
4059multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4060 SDPatternOperator OpNode> {
4061 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4062 asm, ".8b", ".8b",
4063 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4064 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4065 asm, ".16b", ".16b",
4066 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4067 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4068 asm, ".4h", ".4h",
4069 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4070 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4071 asm, ".8h", ".8h",
4072 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4073 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4074 asm, ".2s", ".2s",
4075 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4076 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4077 asm, ".4s", ".4s",
4078 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4079}
4080
4081class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4082 RegisterOperand regtype, string asm, string dstkind,
4083 string srckind, string amount>
4084 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4085 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4086 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4087 Sched<[WriteV]> {
4088 bits<5> Rd;
4089 bits<5> Rn;
4090 let Inst{31} = 0;
4091 let Inst{30} = Q;
4092 let Inst{29-24} = 0b101110;
4093 let Inst{23-22} = size;
4094 let Inst{21-10} = 0b100001001110;
4095 let Inst{9-5} = Rn;
4096 let Inst{4-0} = Rd;
4097}
4098
4099multiclass SIMDVectorLShiftLongBySizeBHS {
4100 let neverHasSideEffects = 1 in {
4101 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4102 "shll", ".8h", ".8b", "8">;
4103 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4104 "shll2", ".8h", ".16b", "8">;
4105 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4106 "shll", ".4s", ".4h", "16">;
4107 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4108 "shll2", ".4s", ".8h", "16">;
4109 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4110 "shll", ".2d", ".2s", "32">;
4111 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4112 "shll2", ".2d", ".4s", "32">;
4113 }
4114}
4115
4116// Supports all element sizes.
4117multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4118 SDPatternOperator OpNode> {
4119 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4120 asm, ".4h", ".8b",
4121 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4122 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4123 asm, ".8h", ".16b",
4124 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4125 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4126 asm, ".2s", ".4h",
4127 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4128 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4129 asm, ".4s", ".8h",
4130 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4131 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4132 asm, ".1d", ".2s",
4133 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4134 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4135 asm, ".2d", ".4s",
4136 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4137}
4138
4139multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4140 SDPatternOperator OpNode> {
4141 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4142 asm, ".4h", ".8b",
4143 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4144 (v8i8 V64:$Rn)))]>;
4145 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4146 asm, ".8h", ".16b",
4147 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4148 (v16i8 V128:$Rn)))]>;
4149 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4150 asm, ".2s", ".4h",
4151 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4152 (v4i16 V64:$Rn)))]>;
4153 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4154 asm, ".4s", ".8h",
4155 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4156 (v8i16 V128:$Rn)))]>;
4157 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4158 asm, ".1d", ".2s",
4159 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4160 (v2i32 V64:$Rn)))]>;
4161 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4162 asm, ".2d", ".4s",
4163 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4164 (v4i32 V128:$Rn)))]>;
4165}
4166
4167// Supports all element sizes, except 1xD.
4168multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4169 SDPatternOperator OpNode> {
4170 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4171 asm, ".8b", ".8b",
4172 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4173 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4174 asm, ".16b", ".16b",
4175 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4176 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4177 asm, ".4h", ".4h",
4178 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4179 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4180 asm, ".8h", ".8h",
4181 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4182 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4183 asm, ".2s", ".2s",
4184 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4185 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4186 asm, ".4s", ".4s",
4187 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4188 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4189 asm, ".2d", ".2d",
4190 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4191}
4192
4193multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4194 SDPatternOperator OpNode = null_frag> {
4195 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4196 asm, ".8b", ".8b",
4197 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4198 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4199 asm, ".16b", ".16b",
4200 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4201 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4202 asm, ".4h", ".4h",
4203 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4204 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4205 asm, ".8h", ".8h",
4206 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4207 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4208 asm, ".2s", ".2s",
4209 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4210 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4211 asm, ".4s", ".4s",
4212 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4213 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4214 asm, ".2d", ".2d",
4215 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4216}
4217
4218
4219// Supports only B element sizes.
4220multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4221 SDPatternOperator OpNode> {
4222 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4223 asm, ".8b", ".8b",
4224 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4225 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4226 asm, ".16b", ".16b",
4227 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4228
4229}
4230
4231// Supports only B and H element sizes.
4232multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4233 SDPatternOperator OpNode> {
4234 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4235 asm, ".8b", ".8b",
4236 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4237 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4238 asm, ".16b", ".16b",
4239 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4240 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4241 asm, ".4h", ".4h",
4242 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4243 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4244 asm, ".8h", ".8h",
4245 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4246}
4247
4248// Supports only S and D element sizes, uses high bit of the size field
4249// as an extra opcode bit.
4250multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4251 SDPatternOperator OpNode> {
4252 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4253 asm, ".2s", ".2s",
4254 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4255 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4256 asm, ".4s", ".4s",
4257 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4258 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4259 asm, ".2d", ".2d",
4260 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4261}
4262
4263// Supports only S element size.
4264multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4265 SDPatternOperator OpNode> {
4266 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4267 asm, ".2s", ".2s",
4268 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4269 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4270 asm, ".4s", ".4s",
4271 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4272}
4273
4274
4275multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4276 SDPatternOperator OpNode> {
4277 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4278 asm, ".2s", ".2s",
4279 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4280 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4281 asm, ".4s", ".4s",
4282 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4283 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4284 asm, ".2d", ".2d",
4285 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4286}
4287
4288multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4289 SDPatternOperator OpNode> {
4290 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4291 asm, ".2s", ".2s",
4292 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4293 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4294 asm, ".4s", ".4s",
4295 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4296 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4297 asm, ".2d", ".2d",
4298 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4299}
4300
4301
4302class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4303 RegisterOperand inreg, RegisterOperand outreg,
4304 string asm, string outkind, string inkind,
4305 list<dag> pattern>
4306 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4307 "{\t$Rd" # outkind # ", $Rn" # inkind #
4308 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4309 Sched<[WriteV]> {
4310 bits<5> Rd;
4311 bits<5> Rn;
4312 let Inst{31} = 0;
4313 let Inst{30} = Q;
4314 let Inst{29} = U;
4315 let Inst{28-24} = 0b01110;
4316 let Inst{23-22} = size;
4317 let Inst{21-17} = 0b10000;
4318 let Inst{16-12} = opcode;
4319 let Inst{11-10} = 0b10;
4320 let Inst{9-5} = Rn;
4321 let Inst{4-0} = Rd;
4322}
4323
4324class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4325 RegisterOperand inreg, RegisterOperand outreg,
4326 string asm, string outkind, string inkind,
4327 list<dag> pattern>
4328 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4329 "{\t$Rd" # outkind # ", $Rn" # inkind #
4330 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4331 Sched<[WriteV]> {
4332 bits<5> Rd;
4333 bits<5> Rn;
4334 let Inst{31} = 0;
4335 let Inst{30} = Q;
4336 let Inst{29} = U;
4337 let Inst{28-24} = 0b01110;
4338 let Inst{23-22} = size;
4339 let Inst{21-17} = 0b10000;
4340 let Inst{16-12} = opcode;
4341 let Inst{11-10} = 0b10;
4342 let Inst{9-5} = Rn;
4343 let Inst{4-0} = Rd;
4344}
4345
4346multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4347 SDPatternOperator OpNode> {
4348 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4349 asm, ".8b", ".8h",
4350 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4351 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4352 asm#"2", ".16b", ".8h", []>;
4353 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4354 asm, ".4h", ".4s",
4355 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4356 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4357 asm#"2", ".8h", ".4s", []>;
4358 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4359 asm, ".2s", ".2d",
4360 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4361 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4362 asm#"2", ".4s", ".2d", []>;
4363
4364 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4365 (!cast<Instruction>(NAME # "v16i8")
4366 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4367 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4368 (!cast<Instruction>(NAME # "v8i16")
4369 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4370 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4371 (!cast<Instruction>(NAME # "v4i32")
4372 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4373}
4374
4375class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4376 RegisterOperand regtype, string asm, string kind,
4377 ValueType dty, ValueType sty, SDNode OpNode>
4378 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4379 "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4380 "|" # kind # "\t$Rd, $Rn, #0}", "",
4381 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4382 Sched<[WriteV]> {
4383 bits<5> Rd;
4384 bits<5> Rn;
4385 let Inst{31} = 0;
4386 let Inst{30} = Q;
4387 let Inst{29} = U;
4388 let Inst{28-24} = 0b01110;
4389 let Inst{23-22} = size;
4390 let Inst{21-17} = 0b10000;
4391 let Inst{16-12} = opcode;
4392 let Inst{11-10} = 0b10;
4393 let Inst{9-5} = Rn;
4394 let Inst{4-0} = Rd;
4395}
4396
4397// Comparisons support all element sizes, except 1xD.
4398multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4399 SDNode OpNode> {
4400 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4401 asm, ".8b",
4402 v8i8, v8i8, OpNode>;
4403 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4404 asm, ".16b",
4405 v16i8, v16i8, OpNode>;
4406 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4407 asm, ".4h",
4408 v4i16, v4i16, OpNode>;
4409 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4410 asm, ".8h",
4411 v8i16, v8i16, OpNode>;
4412 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4413 asm, ".2s",
4414 v2i32, v2i32, OpNode>;
4415 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4416 asm, ".4s",
4417 v4i32, v4i32, OpNode>;
4418 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4419 asm, ".2d",
4420 v2i64, v2i64, OpNode>;
4421}
4422
4423// FP Comparisons support only S and D element sizes.
4424multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4425 string asm, SDNode OpNode> {
4426 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4427 asm, ".2s",
4428 v2i32, v2f32, OpNode>;
4429 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4430 asm, ".4s",
4431 v4i32, v4f32, OpNode>;
4432 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4433 asm, ".2d",
4434 v2i64, v2f64, OpNode>;
4435}
4436
4437let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4438class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4439 RegisterOperand outtype, RegisterOperand intype,
4440 string asm, string VdTy, string VnTy,
4441 list<dag> pattern>
4442 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4443 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4444 Sched<[WriteV]> {
4445 bits<5> Rd;
4446 bits<5> Rn;
4447 let Inst{31} = 0;
4448 let Inst{30} = Q;
4449 let Inst{29} = U;
4450 let Inst{28-24} = 0b01110;
4451 let Inst{23-22} = size;
4452 let Inst{21-17} = 0b10000;
4453 let Inst{16-12} = opcode;
4454 let Inst{11-10} = 0b10;
4455 let Inst{9-5} = Rn;
4456 let Inst{4-0} = Rd;
4457}
4458
4459class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4460 RegisterOperand outtype, RegisterOperand intype,
4461 string asm, string VdTy, string VnTy,
4462 list<dag> pattern>
4463 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4464 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4465 Sched<[WriteV]> {
4466 bits<5> Rd;
4467 bits<5> Rn;
4468 let Inst{31} = 0;
4469 let Inst{30} = Q;
4470 let Inst{29} = U;
4471 let Inst{28-24} = 0b01110;
4472 let Inst{23-22} = size;
4473 let Inst{21-17} = 0b10000;
4474 let Inst{16-12} = opcode;
4475 let Inst{11-10} = 0b10;
4476 let Inst{9-5} = Rn;
4477 let Inst{4-0} = Rd;
4478}
4479
4480multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4481 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4482 asm, ".4s", ".4h", []>;
4483 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4484 asm#"2", ".4s", ".8h", []>;
4485 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4486 asm, ".2d", ".2s", []>;
4487 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4488 asm#"2", ".2d", ".4s", []>;
4489}
4490
4491multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4492 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4493 asm, ".4h", ".4s", []>;
4494 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4495 asm#"2", ".8h", ".4s", []>;
4496 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4497 asm, ".2s", ".2d", []>;
4498 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4499 asm#"2", ".4s", ".2d", []>;
4500}
4501
4502multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4503 Intrinsic OpNode> {
4504 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4505 asm, ".2s", ".2d",
4506 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4507 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4508 asm#"2", ".4s", ".2d", []>;
4509
4510 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4511 (!cast<Instruction>(NAME # "v4f32")
4512 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4513}
4514
4515//----------------------------------------------------------------------------
4516// AdvSIMD three register different-size vector instructions.
4517//----------------------------------------------------------------------------
4518
4519let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4520class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4521 RegisterOperand outtype, RegisterOperand intype1,
4522 RegisterOperand intype2, string asm,
4523 string outkind, string inkind1, string inkind2,
4524 list<dag> pattern>
4525 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4526 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4527 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4528 Sched<[WriteV]> {
4529 bits<5> Rd;
4530 bits<5> Rn;
4531 bits<5> Rm;
4532 let Inst{31} = 0;
4533 let Inst{30} = size{0};
4534 let Inst{29} = U;
4535 let Inst{28-24} = 0b01110;
4536 let Inst{23-22} = size{2-1};
4537 let Inst{21} = 1;
4538 let Inst{20-16} = Rm;
4539 let Inst{15-12} = opcode;
4540 let Inst{11-10} = 0b00;
4541 let Inst{9-5} = Rn;
4542 let Inst{4-0} = Rd;
4543}
4544
4545let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4546class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4547 RegisterOperand outtype, RegisterOperand intype1,
4548 RegisterOperand intype2, string asm,
4549 string outkind, string inkind1, string inkind2,
4550 list<dag> pattern>
4551 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4552 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4553 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4554 Sched<[WriteV]> {
4555 bits<5> Rd;
4556 bits<5> Rn;
4557 bits<5> Rm;
4558 let Inst{31} = 0;
4559 let Inst{30} = size{0};
4560 let Inst{29} = U;
4561 let Inst{28-24} = 0b01110;
4562 let Inst{23-22} = size{2-1};
4563 let Inst{21} = 1;
4564 let Inst{20-16} = Rm;
4565 let Inst{15-12} = opcode;
4566 let Inst{11-10} = 0b00;
4567 let Inst{9-5} = Rn;
4568 let Inst{4-0} = Rd;
4569}
4570
4571// FIXME: TableGen doesn't know how to deal with expanded types that also
4572// change the element count (in this case, placing the results in
4573// the high elements of the result register rather than the low
4574// elements). Until that's fixed, we can't code-gen those.
4575multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4576 Intrinsic IntOp> {
4577 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4578 V64, V128, V128,
4579 asm, ".8b", ".8h", ".8h",
4580 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4581 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4582 V128, V128, V128,
4583 asm#"2", ".16b", ".8h", ".8h",
4584 []>;
4585 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4586 V64, V128, V128,
4587 asm, ".4h", ".4s", ".4s",
4588 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4589 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4590 V128, V128, V128,
4591 asm#"2", ".8h", ".4s", ".4s",
4592 []>;
4593 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4594 V64, V128, V128,
4595 asm, ".2s", ".2d", ".2d",
4596 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4597 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4598 V128, V128, V128,
4599 asm#"2", ".4s", ".2d", ".2d",
4600 []>;
4601
4602
4603 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4604 // a version attached to an instruction.
4605 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4606 (v8i16 V128:$Rm))),
4607 (!cast<Instruction>(NAME # "v8i16_v16i8")
4608 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4609 V128:$Rn, V128:$Rm)>;
4610 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4611 (v4i32 V128:$Rm))),
4612 (!cast<Instruction>(NAME # "v4i32_v8i16")
4613 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4614 V128:$Rn, V128:$Rm)>;
4615 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4616 (v2i64 V128:$Rm))),
4617 (!cast<Instruction>(NAME # "v2i64_v4i32")
4618 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4619 V128:$Rn, V128:$Rm)>;
4620}
4621
4622multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4623 Intrinsic IntOp> {
4624 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4625 V128, V64, V64,
4626 asm, ".8h", ".8b", ".8b",
4627 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4628 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4629 V128, V128, V128,
4630 asm#"2", ".8h", ".16b", ".16b", []>;
4631 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4632 V128, V64, V64,
4633 asm, ".1q", ".1d", ".1d", []>;
4634 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4635 V128, V128, V128,
4636 asm#"2", ".1q", ".2d", ".2d", []>;
4637
4638 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4639 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4640 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4641}
4642
4643multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4644 SDPatternOperator OpNode> {
4645 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4646 V128, V64, V64,
4647 asm, ".4s", ".4h", ".4h",
4648 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4649 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4650 V128, V128, V128,
4651 asm#"2", ".4s", ".8h", ".8h",
4652 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4653 (extract_high_v8i16 V128:$Rm)))]>;
4654 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4655 V128, V64, V64,
4656 asm, ".2d", ".2s", ".2s",
4657 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4658 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4659 V128, V128, V128,
4660 asm#"2", ".2d", ".4s", ".4s",
4661 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4662 (extract_high_v4i32 V128:$Rm)))]>;
4663}
4664
4665multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4666 SDPatternOperator OpNode = null_frag> {
4667 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4668 V128, V64, V64,
4669 asm, ".8h", ".8b", ".8b",
4670 [(set (v8i16 V128:$Rd),
4671 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4672 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4673 V128, V128, V128,
4674 asm#"2", ".8h", ".16b", ".16b",
4675 [(set (v8i16 V128:$Rd),
4676 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4677 (extract_high_v16i8 V128:$Rm)))))]>;
4678 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4679 V128, V64, V64,
4680 asm, ".4s", ".4h", ".4h",
4681 [(set (v4i32 V128:$Rd),
4682 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4683 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4684 V128, V128, V128,
4685 asm#"2", ".4s", ".8h", ".8h",
4686 [(set (v4i32 V128:$Rd),
4687 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4688 (extract_high_v8i16 V128:$Rm)))))]>;
4689 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4690 V128, V64, V64,
4691 asm, ".2d", ".2s", ".2s",
4692 [(set (v2i64 V128:$Rd),
4693 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4694 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4695 V128, V128, V128,
4696 asm#"2", ".2d", ".4s", ".4s",
4697 [(set (v2i64 V128:$Rd),
4698 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4699 (extract_high_v4i32 V128:$Rm)))))]>;
4700}
4701
4702multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4703 string asm,
4704 SDPatternOperator OpNode> {
4705 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4706 V128, V64, V64,
4707 asm, ".8h", ".8b", ".8b",
4708 [(set (v8i16 V128:$dst),
4709 (add (v8i16 V128:$Rd),
4710 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4711 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4712 V128, V128, V128,
4713 asm#"2", ".8h", ".16b", ".16b",
4714 [(set (v8i16 V128:$dst),
4715 (add (v8i16 V128:$Rd),
4716 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4717 (extract_high_v16i8 V128:$Rm))))))]>;
4718 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4719 V128, V64, V64,
4720 asm, ".4s", ".4h", ".4h",
4721 [(set (v4i32 V128:$dst),
4722 (add (v4i32 V128:$Rd),
4723 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4724 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4725 V128, V128, V128,
4726 asm#"2", ".4s", ".8h", ".8h",
4727 [(set (v4i32 V128:$dst),
4728 (add (v4i32 V128:$Rd),
4729 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4730 (extract_high_v8i16 V128:$Rm))))))]>;
4731 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4732 V128, V64, V64,
4733 asm, ".2d", ".2s", ".2s",
4734 [(set (v2i64 V128:$dst),
4735 (add (v2i64 V128:$Rd),
4736 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4737 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4738 V128, V128, V128,
4739 asm#"2", ".2d", ".4s", ".4s",
4740 [(set (v2i64 V128:$dst),
4741 (add (v2i64 V128:$Rd),
4742 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4743 (extract_high_v4i32 V128:$Rm))))))]>;
4744}
4745
4746multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4747 SDPatternOperator OpNode = null_frag> {
4748 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4749 V128, V64, V64,
4750 asm, ".8h", ".8b", ".8b",
4751 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4752 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4753 V128, V128, V128,
4754 asm#"2", ".8h", ".16b", ".16b",
4755 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4756 (extract_high_v16i8 V128:$Rm)))]>;
4757 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4758 V128, V64, V64,
4759 asm, ".4s", ".4h", ".4h",
4760 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4761 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4762 V128, V128, V128,
4763 asm#"2", ".4s", ".8h", ".8h",
4764 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4765 (extract_high_v8i16 V128:$Rm)))]>;
4766 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4767 V128, V64, V64,
4768 asm, ".2d", ".2s", ".2s",
4769 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4770 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4771 V128, V128, V128,
4772 asm#"2", ".2d", ".4s", ".4s",
4773 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4774 (extract_high_v4i32 V128:$Rm)))]>;
4775}
4776
4777multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4778 string asm,
4779 SDPatternOperator OpNode> {
4780 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4781 V128, V64, V64,
4782 asm, ".8h", ".8b", ".8b",
4783 [(set (v8i16 V128:$dst),
4784 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4785 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4786 V128, V128, V128,
4787 asm#"2", ".8h", ".16b", ".16b",
4788 [(set (v8i16 V128:$dst),
4789 (OpNode (v8i16 V128:$Rd),
4790 (extract_high_v16i8 V128:$Rn),
4791 (extract_high_v16i8 V128:$Rm)))]>;
4792 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4793 V128, V64, V64,
4794 asm, ".4s", ".4h", ".4h",
4795 [(set (v4i32 V128:$dst),
4796 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4797 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4798 V128, V128, V128,
4799 asm#"2", ".4s", ".8h", ".8h",
4800 [(set (v4i32 V128:$dst),
4801 (OpNode (v4i32 V128:$Rd),
4802 (extract_high_v8i16 V128:$Rn),
4803 (extract_high_v8i16 V128:$Rm)))]>;
4804 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4805 V128, V64, V64,
4806 asm, ".2d", ".2s", ".2s",
4807 [(set (v2i64 V128:$dst),
4808 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4809 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4810 V128, V128, V128,
4811 asm#"2", ".2d", ".4s", ".4s",
4812 [(set (v2i64 V128:$dst),
4813 (OpNode (v2i64 V128:$Rd),
4814 (extract_high_v4i32 V128:$Rn),
4815 (extract_high_v4i32 V128:$Rm)))]>;
4816}
4817
4818multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4819 SDPatternOperator Accum> {
4820 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4821 V128, V64, V64,
4822 asm, ".4s", ".4h", ".4h",
4823 [(set (v4i32 V128:$dst),
4824 (Accum (v4i32 V128:$Rd),
4825 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4826 (v4i16 V64:$Rm)))))]>;
4827 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4828 V128, V128, V128,
4829 asm#"2", ".4s", ".8h", ".8h",
4830 [(set (v4i32 V128:$dst),
4831 (Accum (v4i32 V128:$Rd),
4832 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4833 (extract_high_v8i16 V128:$Rm)))))]>;
4834 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4835 V128, V64, V64,
4836 asm, ".2d", ".2s", ".2s",
4837 [(set (v2i64 V128:$dst),
4838 (Accum (v2i64 V128:$Rd),
4839 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4840 (v2i32 V64:$Rm)))))]>;
4841 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4842 V128, V128, V128,
4843 asm#"2", ".2d", ".4s", ".4s",
4844 [(set (v2i64 V128:$dst),
4845 (Accum (v2i64 V128:$Rd),
4846 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4847 (extract_high_v4i32 V128:$Rm)))))]>;
4848}
4849
4850multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4851 SDPatternOperator OpNode> {
4852 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4853 V128, V128, V64,
4854 asm, ".8h", ".8h", ".8b",
4855 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4856 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4857 V128, V128, V128,
4858 asm#"2", ".8h", ".8h", ".16b",
4859 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4860 (extract_high_v16i8 V128:$Rm)))]>;
4861 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4862 V128, V128, V64,
4863 asm, ".4s", ".4s", ".4h",
4864 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4865 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4866 V128, V128, V128,
4867 asm#"2", ".4s", ".4s", ".8h",
4868 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4869 (extract_high_v8i16 V128:$Rm)))]>;
4870 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4871 V128, V128, V64,
4872 asm, ".2d", ".2d", ".2s",
4873 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4874 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4875 V128, V128, V128,
4876 asm#"2", ".2d", ".2d", ".4s",
4877 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4878 (extract_high_v4i32 V128:$Rm)))]>;
4879}
4880
4881//----------------------------------------------------------------------------
4882// AdvSIMD bitwise extract from vector
4883//----------------------------------------------------------------------------
4884
4885class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4886 string asm, string kind>
4887 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4888 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4889 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4890 [(set (vty regtype:$Rd),
4891 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4892 Sched<[WriteV]> {
4893 bits<5> Rd;
4894 bits<5> Rn;
4895 bits<5> Rm;
4896 bits<4> imm;
4897 let Inst{31} = 0;
4898 let Inst{30} = size;
4899 let Inst{29-21} = 0b101110000;
4900 let Inst{20-16} = Rm;
4901 let Inst{15} = 0;
4902 let Inst{14-11} = imm;
4903 let Inst{10} = 0;
4904 let Inst{9-5} = Rn;
4905 let Inst{4-0} = Rd;
4906}
4907
4908
4909multiclass SIMDBitwiseExtract<string asm> {
Bradley Smithdb7b9b12014-04-09 14:43:31 +00004910 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4911 let imm{3} = 0;
4912 }
Tim Northover00ed9962014-03-29 10:18:08 +00004913 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4914}
4915
4916//----------------------------------------------------------------------------
4917// AdvSIMD zip vector
4918//----------------------------------------------------------------------------
4919
4920class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4921 string asm, string kind, SDNode OpNode, ValueType valty>
4922 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4923 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4924 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4925 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4926 Sched<[WriteV]> {
4927 bits<5> Rd;
4928 bits<5> Rn;
4929 bits<5> Rm;
4930 let Inst{31} = 0;
4931 let Inst{30} = size{0};
4932 let Inst{29-24} = 0b001110;
4933 let Inst{23-22} = size{2-1};
4934 let Inst{21} = 0;
4935 let Inst{20-16} = Rm;
4936 let Inst{15} = 0;
4937 let Inst{14-12} = opc;
4938 let Inst{11-10} = 0b10;
4939 let Inst{9-5} = Rn;
4940 let Inst{4-0} = Rd;
4941}
4942
4943multiclass SIMDZipVector<bits<3>opc, string asm,
4944 SDNode OpNode> {
4945 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
4946 asm, ".8b", OpNode, v8i8>;
4947 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
4948 asm, ".16b", OpNode, v16i8>;
4949 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
4950 asm, ".4h", OpNode, v4i16>;
4951 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
4952 asm, ".8h", OpNode, v8i16>;
4953 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
4954 asm, ".2s", OpNode, v2i32>;
4955 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
4956 asm, ".4s", OpNode, v4i32>;
4957 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
4958 asm, ".2d", OpNode, v2i64>;
4959
4960 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4961 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4962 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4963 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4964 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4965 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4966}
4967
4968//----------------------------------------------------------------------------
4969// AdvSIMD three register scalar instructions
4970//----------------------------------------------------------------------------
4971
4972let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4973class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4974 RegisterClass regtype, string asm,
4975 list<dag> pattern>
4976 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4977 "\t$Rd, $Rn, $Rm", "", pattern>,
4978 Sched<[WriteV]> {
4979 bits<5> Rd;
4980 bits<5> Rn;
4981 bits<5> Rm;
4982 let Inst{31-30} = 0b01;
4983 let Inst{29} = U;
4984 let Inst{28-24} = 0b11110;
4985 let Inst{23-22} = size;
4986 let Inst{21} = 1;
4987 let Inst{20-16} = Rm;
4988 let Inst{15-11} = opcode;
4989 let Inst{10} = 1;
4990 let Inst{9-5} = Rn;
4991 let Inst{4-0} = Rd;
4992}
4993
4994multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4995 SDPatternOperator OpNode> {
4996 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4997 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4998}
4999
5000multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5001 SDPatternOperator OpNode> {
5002 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5003 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5004 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5005 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5006 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5007
5008 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5009 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5010 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5011 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5012}
5013
5014multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5015 SDPatternOperator OpNode> {
5016 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5017 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5018 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5019}
5020
5021multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5022 SDPatternOperator OpNode = null_frag> {
5023 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5024 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5025 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5026 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5027 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5028 }
5029
5030 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5031 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5032}
5033
5034multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5035 SDPatternOperator OpNode = null_frag> {
5036 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5037 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5038 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5039 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5040 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5041 }
5042
5043 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5044 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5045}
5046
5047class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5048 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5049 : I<oops, iops, asm,
5050 "\t$Rd, $Rn, $Rm", cstr, pat>,
5051 Sched<[WriteV]> {
5052 bits<5> Rd;
5053 bits<5> Rn;
5054 bits<5> Rm;
5055 let Inst{31-30} = 0b01;
5056 let Inst{29} = U;
5057 let Inst{28-24} = 0b11110;
5058 let Inst{23-22} = size;
5059 let Inst{21} = 1;
5060 let Inst{20-16} = Rm;
5061 let Inst{15-11} = opcode;
5062 let Inst{10} = 0;
5063 let Inst{9-5} = Rn;
5064 let Inst{4-0} = Rd;
5065}
5066
5067let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5068multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5069 SDPatternOperator OpNode = null_frag> {
5070 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5071 (outs FPR32:$Rd),
5072 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5073 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5074 (outs FPR64:$Rd),
5075 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5076 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5077}
5078
5079let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5080multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5081 SDPatternOperator OpNode = null_frag> {
5082 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5083 (outs FPR32:$dst),
5084 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5085 asm, "$Rd = $dst", []>;
5086 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5087 (outs FPR64:$dst),
5088 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5089 asm, "$Rd = $dst",
5090 [(set (i64 FPR64:$dst),
5091 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5092}
5093
5094//----------------------------------------------------------------------------
5095// AdvSIMD two register scalar instructions
5096//----------------------------------------------------------------------------
5097
5098let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5099class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5100 RegisterClass regtype, RegisterClass regtype2,
5101 string asm, list<dag> pat>
5102 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5103 "\t$Rd, $Rn", "", pat>,
5104 Sched<[WriteV]> {
5105 bits<5> Rd;
5106 bits<5> Rn;
5107 let Inst{31-30} = 0b01;
5108 let Inst{29} = U;
5109 let Inst{28-24} = 0b11110;
5110 let Inst{23-22} = size;
5111 let Inst{21-17} = 0b10000;
5112 let Inst{16-12} = opcode;
5113 let Inst{11-10} = 0b10;
5114 let Inst{9-5} = Rn;
5115 let Inst{4-0} = Rd;
5116}
5117
5118let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5119class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5120 RegisterClass regtype, RegisterClass regtype2,
5121 string asm, list<dag> pat>
5122 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5123 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5124 Sched<[WriteV]> {
5125 bits<5> Rd;
5126 bits<5> Rn;
5127 let Inst{31-30} = 0b01;
5128 let Inst{29} = U;
5129 let Inst{28-24} = 0b11110;
5130 let Inst{23-22} = size;
5131 let Inst{21-17} = 0b10000;
5132 let Inst{16-12} = opcode;
5133 let Inst{11-10} = 0b10;
5134 let Inst{9-5} = Rn;
5135 let Inst{4-0} = Rd;
5136}
5137
5138
5139let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5140class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5141 RegisterClass regtype, string asm>
5142 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5143 "\t$Rd, $Rn, #0", "", []>,
5144 Sched<[WriteV]> {
5145 bits<5> Rd;
5146 bits<5> Rn;
5147 let Inst{31-30} = 0b01;
5148 let Inst{29} = U;
5149 let Inst{28-24} = 0b11110;
5150 let Inst{23-22} = size;
5151 let Inst{21-17} = 0b10000;
5152 let Inst{16-12} = opcode;
5153 let Inst{11-10} = 0b10;
5154 let Inst{9-5} = Rn;
5155 let Inst{4-0} = Rd;
5156}
5157
5158class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5159 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5160 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5161 Sched<[WriteV]> {
5162 bits<5> Rd;
5163 bits<5> Rn;
5164 let Inst{31-17} = 0b011111100110000;
5165 let Inst{16-12} = opcode;
5166 let Inst{11-10} = 0b10;
5167 let Inst{9-5} = Rn;
5168 let Inst{4-0} = Rd;
5169}
5170
5171multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5172 SDPatternOperator OpNode> {
5173 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5174
5175 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5176 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5177}
5178
5179multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5180 SDPatternOperator OpNode> {
5181 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5182 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5183
5184 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5185 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5186}
5187
5188multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5189 SDPatternOperator OpNode = null_frag> {
5190 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5191 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
Tim Northoverf4810362014-03-31 15:46:17 +00005192
5193 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5194 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005195}
5196
5197multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5198 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5199 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5200}
5201
5202multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5203 SDPatternOperator OpNode> {
5204 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5205 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5206 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5207 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5208}
5209
5210multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5211 SDPatternOperator OpNode = null_frag> {
5212 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5213 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5214 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5215 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5216 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5217 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5218 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5219 }
5220
5221 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5222 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5223}
5224
Tim Northover00ed9962014-03-29 10:18:08 +00005225multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5226 Intrinsic OpNode> {
Tim Northover903814c2014-03-31 15:46:26 +00005227 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5228 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5229 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5230 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5231 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5232 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5233 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5234 }
5235
5236 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5237 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005238}
5239
5240
5241
5242let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5243multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5244 SDPatternOperator OpNode = null_frag> {
5245 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5246 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5247 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5248 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5249}
5250
5251//----------------------------------------------------------------------------
5252// AdvSIMD scalar pairwise instructions
5253//----------------------------------------------------------------------------
5254
5255let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5256class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5257 RegisterOperand regtype, RegisterOperand vectype,
5258 string asm, string kind>
5259 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5260 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5261 Sched<[WriteV]> {
5262 bits<5> Rd;
5263 bits<5> Rn;
5264 let Inst{31-30} = 0b01;
5265 let Inst{29} = U;
5266 let Inst{28-24} = 0b11110;
5267 let Inst{23-22} = size;
5268 let Inst{21-17} = 0b11000;
5269 let Inst{16-12} = opcode;
5270 let Inst{11-10} = 0b10;
5271 let Inst{9-5} = Rn;
5272 let Inst{4-0} = Rd;
5273}
5274
5275multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5276 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5277 asm, ".2d">;
5278}
5279
5280multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5281 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5282 asm, ".2s">;
5283 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5284 asm, ".2d">;
5285}
5286
5287//----------------------------------------------------------------------------
5288// AdvSIMD across lanes instructions
5289//----------------------------------------------------------------------------
5290
5291let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5292class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5293 RegisterClass regtype, RegisterOperand vectype,
5294 string asm, string kind, list<dag> pattern>
5295 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5296 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5297 Sched<[WriteV]> {
5298 bits<5> Rd;
5299 bits<5> Rn;
5300 let Inst{31} = 0;
5301 let Inst{30} = Q;
5302 let Inst{29} = U;
5303 let Inst{28-24} = 0b01110;
5304 let Inst{23-22} = size;
5305 let Inst{21-17} = 0b11000;
5306 let Inst{16-12} = opcode;
5307 let Inst{11-10} = 0b10;
5308 let Inst{9-5} = Rn;
5309 let Inst{4-0} = Rd;
5310}
5311
5312multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5313 string asm> {
5314 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5315 asm, ".8b", []>;
5316 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5317 asm, ".16b", []>;
5318 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5319 asm, ".4h", []>;
5320 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5321 asm, ".8h", []>;
5322 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5323 asm, ".4s", []>;
5324}
5325
5326multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5327 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5328 asm, ".8b", []>;
5329 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5330 asm, ".16b", []>;
5331 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5332 asm, ".4h", []>;
5333 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5334 asm, ".8h", []>;
5335 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5336 asm, ".4s", []>;
5337}
5338
5339multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5340 Intrinsic intOp> {
5341 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5342 asm, ".4s",
5343 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5344}
5345
5346//----------------------------------------------------------------------------
5347// AdvSIMD INS/DUP instructions
5348//----------------------------------------------------------------------------
5349
5350// FIXME: There has got to be a better way to factor these. ugh.
5351
5352class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5353 string operands, string constraints, list<dag> pattern>
5354 : I<outs, ins, asm, operands, constraints, pattern>,
5355 Sched<[WriteV]> {
5356 bits<5> Rd;
5357 bits<5> Rn;
5358 let Inst{31} = 0;
5359 let Inst{30} = Q;
5360 let Inst{29} = op;
5361 let Inst{28-21} = 0b01110000;
5362 let Inst{15} = 0;
5363 let Inst{10} = 1;
5364 let Inst{9-5} = Rn;
5365 let Inst{4-0} = Rd;
5366}
5367
5368class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5369 RegisterOperand vecreg, RegisterClass regtype>
5370 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5371 "{\t$Rd" # size # ", $Rn" #
5372 "|" # size # "\t$Rd, $Rn}", "",
5373 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5374 let Inst{20-16} = imm5;
5375 let Inst{14-11} = 0b0001;
5376}
5377
5378class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5379 ValueType vectype, ValueType insreg,
5380 RegisterOperand vecreg, Operand idxtype,
5381 ValueType elttype, SDNode OpNode>
5382 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5383 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5384 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5385 [(set (vectype vecreg:$Rd),
5386 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5387 let Inst{14-11} = 0b0000;
5388}
5389
5390class SIMDDup64FromElement
5391 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5392 VectorIndexD, i64, ARM64duplane64> {
5393 bits<1> idx;
5394 let Inst{20} = idx;
5395 let Inst{19-16} = 0b1000;
5396}
5397
5398class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5399 RegisterOperand vecreg>
5400 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5401 VectorIndexS, i64, ARM64duplane32> {
5402 bits<2> idx;
5403 let Inst{20-19} = idx;
5404 let Inst{18-16} = 0b100;
5405}
5406
5407class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5408 RegisterOperand vecreg>
5409 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5410 VectorIndexH, i64, ARM64duplane16> {
5411 bits<3> idx;
5412 let Inst{20-18} = idx;
5413 let Inst{17-16} = 0b10;
5414}
5415
5416class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5417 RegisterOperand vecreg>
5418 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5419 VectorIndexB, i64, ARM64duplane8> {
5420 bits<4> idx;
5421 let Inst{20-17} = idx;
5422 let Inst{16} = 1;
5423}
5424
5425class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5426 Operand idxtype, string asm, list<dag> pattern>
5427 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5428 "{\t$Rd, $Rn" # size # "$idx" #
5429 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5430 let Inst{14-11} = imm4;
5431}
5432
5433class SIMDSMov<bit Q, string size, RegisterClass regtype,
5434 Operand idxtype>
5435 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5436class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5437 Operand idxtype>
5438 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5439 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5440
5441class SIMDMovAlias<string asm, string size, Instruction inst,
5442 RegisterClass regtype, Operand idxtype>
5443 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5444 "|" # size # "\t$dst, $src$idx}",
5445 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5446
5447multiclass SMov {
5448 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5449 bits<4> idx;
5450 let Inst{20-17} = idx;
5451 let Inst{16} = 1;
5452 }
5453 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5454 bits<4> idx;
5455 let Inst{20-17} = idx;
5456 let Inst{16} = 1;
5457 }
5458 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5459 bits<3> idx;
5460 let Inst{20-18} = idx;
5461 let Inst{17-16} = 0b10;
5462 }
5463 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5464 bits<3> idx;
5465 let Inst{20-18} = idx;
5466 let Inst{17-16} = 0b10;
5467 }
5468 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5469 bits<2> idx;
5470 let Inst{20-19} = idx;
5471 let Inst{18-16} = 0b100;
5472 }
5473}
5474
5475multiclass UMov {
5476 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5477 bits<4> idx;
5478 let Inst{20-17} = idx;
5479 let Inst{16} = 1;
5480 }
5481 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5482 bits<3> idx;
5483 let Inst{20-18} = idx;
5484 let Inst{17-16} = 0b10;
5485 }
5486 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5487 bits<2> idx;
5488 let Inst{20-19} = idx;
5489 let Inst{18-16} = 0b100;
5490 }
5491 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5492 bits<1> idx;
5493 let Inst{20} = idx;
5494 let Inst{19-16} = 0b1000;
5495 }
5496 def : SIMDMovAlias<"mov", ".s",
5497 !cast<Instruction>(NAME#"vi32"),
5498 GPR32, VectorIndexS>;
5499 def : SIMDMovAlias<"mov", ".d",
5500 !cast<Instruction>(NAME#"vi64"),
5501 GPR64, VectorIndexD>;
5502}
5503
5504class SIMDInsFromMain<string size, ValueType vectype,
5505 RegisterClass regtype, Operand idxtype>
5506 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5507 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5508 "{\t$Rd" # size # "$idx, $Rn" #
5509 "|" # size # "\t$Rd$idx, $Rn}",
5510 "$Rd = $dst",
5511 [(set V128:$dst,
5512 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5513 let Inst{14-11} = 0b0011;
5514}
5515
5516class SIMDInsFromElement<string size, ValueType vectype,
5517 ValueType elttype, Operand idxtype>
5518 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5519 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5520 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5521 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5522 "$Rd = $dst",
5523 [(set V128:$dst,
5524 (vector_insert
5525 (vectype V128:$Rd),
5526 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5527 idxtype:$idx))]>;
5528
5529class SIMDInsMainMovAlias<string size, Instruction inst,
5530 RegisterClass regtype, Operand idxtype>
5531 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5532 "|" # size #"\t$dst$idx, $src}",
5533 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5534class SIMDInsElementMovAlias<string size, Instruction inst,
5535 Operand idxtype>
5536 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5537 # "|" # size #" $dst$idx, $src$idx2}",
5538 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5539
5540
5541multiclass SIMDIns {
5542 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5543 bits<4> idx;
5544 let Inst{20-17} = idx;
5545 let Inst{16} = 1;
5546 }
5547 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5548 bits<3> idx;
5549 let Inst{20-18} = idx;
5550 let Inst{17-16} = 0b10;
5551 }
5552 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5553 bits<2> idx;
5554 let Inst{20-19} = idx;
5555 let Inst{18-16} = 0b100;
5556 }
5557 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5558 bits<1> idx;
5559 let Inst{20} = idx;
5560 let Inst{19-16} = 0b1000;
5561 }
5562
5563 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5564 bits<4> idx;
5565 bits<4> idx2;
5566 let Inst{20-17} = idx;
5567 let Inst{16} = 1;
5568 let Inst{14-11} = idx2;
5569 }
5570 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5571 bits<3> idx;
5572 bits<3> idx2;
5573 let Inst{20-18} = idx;
5574 let Inst{17-16} = 0b10;
5575 let Inst{14-12} = idx2;
5576 let Inst{11} = 0;
5577 }
5578 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5579 bits<2> idx;
5580 bits<2> idx2;
5581 let Inst{20-19} = idx;
5582 let Inst{18-16} = 0b100;
5583 let Inst{14-13} = idx2;
5584 let Inst{12-11} = 0;
5585 }
5586 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5587 bits<1> idx;
5588 bits<1> idx2;
5589 let Inst{20} = idx;
5590 let Inst{19-16} = 0b1000;
5591 let Inst{14} = idx2;
5592 let Inst{13-11} = 0;
5593 }
5594
5595 // For all forms of the INS instruction, the "mov" mnemonic is the
5596 // preferred alias. Why they didn't just call the instruction "mov" in
5597 // the first place is a very good question indeed...
5598 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5599 GPR32, VectorIndexB>;
5600 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5601 GPR32, VectorIndexH>;
5602 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5603 GPR32, VectorIndexS>;
5604 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5605 GPR64, VectorIndexD>;
5606
5607 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5608 VectorIndexB>;
5609 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5610 VectorIndexH>;
5611 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5612 VectorIndexS>;
5613 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5614 VectorIndexD>;
5615}
5616
5617//----------------------------------------------------------------------------
5618// AdvSIMD TBL/TBX
5619//----------------------------------------------------------------------------
5620
5621let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5622class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5623 RegisterOperand listtype, string asm, string kind>
5624 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5625 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5626 Sched<[WriteV]> {
5627 bits<5> Vd;
5628 bits<5> Vn;
5629 bits<5> Vm;
5630 let Inst{31} = 0;
5631 let Inst{30} = Q;
5632 let Inst{29-21} = 0b001110000;
5633 let Inst{20-16} = Vm;
5634 let Inst{15} = 0;
5635 let Inst{14-13} = len;
5636 let Inst{12} = op;
5637 let Inst{11-10} = 0b00;
5638 let Inst{9-5} = Vn;
5639 let Inst{4-0} = Vd;
5640}
5641
5642let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5643class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5644 RegisterOperand listtype, string asm, string kind>
5645 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5646 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5647 Sched<[WriteV]> {
5648 bits<5> Vd;
5649 bits<5> Vn;
5650 bits<5> Vm;
5651 let Inst{31} = 0;
5652 let Inst{30} = Q;
5653 let Inst{29-21} = 0b001110000;
5654 let Inst{20-16} = Vm;
5655 let Inst{15} = 0;
5656 let Inst{14-13} = len;
5657 let Inst{12} = op;
5658 let Inst{11-10} = 0b00;
5659 let Inst{9-5} = Vn;
5660 let Inst{4-0} = Vd;
5661}
5662
5663class SIMDTableLookupAlias<string asm, Instruction inst,
5664 RegisterOperand vectype, RegisterOperand listtype>
5665 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5666 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5667
5668multiclass SIMDTableLookup<bit op, string asm> {
5669 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5670 asm, ".8b">;
5671 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5672 asm, ".8b">;
5673 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5674 asm, ".8b">;
5675 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5676 asm, ".8b">;
5677 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5678 asm, ".16b">;
5679 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5680 asm, ".16b">;
5681 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5682 asm, ".16b">;
5683 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5684 asm, ".16b">;
5685
5686 def : SIMDTableLookupAlias<asm # ".8b",
5687 !cast<Instruction>(NAME#"v8i8One"),
5688 V64, VecListOne128>;
5689 def : SIMDTableLookupAlias<asm # ".8b",
5690 !cast<Instruction>(NAME#"v8i8Two"),
5691 V64, VecListTwo128>;
5692 def : SIMDTableLookupAlias<asm # ".8b",
5693 !cast<Instruction>(NAME#"v8i8Three"),
5694 V64, VecListThree128>;
5695 def : SIMDTableLookupAlias<asm # ".8b",
5696 !cast<Instruction>(NAME#"v8i8Four"),
5697 V64, VecListFour128>;
5698 def : SIMDTableLookupAlias<asm # ".16b",
5699 !cast<Instruction>(NAME#"v16i8One"),
5700 V128, VecListOne128>;
5701 def : SIMDTableLookupAlias<asm # ".16b",
5702 !cast<Instruction>(NAME#"v16i8Two"),
5703 V128, VecListTwo128>;
5704 def : SIMDTableLookupAlias<asm # ".16b",
5705 !cast<Instruction>(NAME#"v16i8Three"),
5706 V128, VecListThree128>;
5707 def : SIMDTableLookupAlias<asm # ".16b",
5708 !cast<Instruction>(NAME#"v16i8Four"),
5709 V128, VecListFour128>;
5710}
5711
5712multiclass SIMDTableLookupTied<bit op, string asm> {
5713 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5714 asm, ".8b">;
5715 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5716 asm, ".8b">;
5717 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5718 asm, ".8b">;
5719 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5720 asm, ".8b">;
5721 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5722 asm, ".16b">;
5723 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5724 asm, ".16b">;
5725 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5726 asm, ".16b">;
5727 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5728 asm, ".16b">;
5729
5730 def : SIMDTableLookupAlias<asm # ".8b",
5731 !cast<Instruction>(NAME#"v8i8One"),
5732 V64, VecListOne128>;
5733 def : SIMDTableLookupAlias<asm # ".8b",
5734 !cast<Instruction>(NAME#"v8i8Two"),
5735 V64, VecListTwo128>;
5736 def : SIMDTableLookupAlias<asm # ".8b",
5737 !cast<Instruction>(NAME#"v8i8Three"),
5738 V64, VecListThree128>;
5739 def : SIMDTableLookupAlias<asm # ".8b",
5740 !cast<Instruction>(NAME#"v8i8Four"),
5741 V64, VecListFour128>;
5742 def : SIMDTableLookupAlias<asm # ".16b",
5743 !cast<Instruction>(NAME#"v16i8One"),
5744 V128, VecListOne128>;
5745 def : SIMDTableLookupAlias<asm # ".16b",
5746 !cast<Instruction>(NAME#"v16i8Two"),
5747 V128, VecListTwo128>;
5748 def : SIMDTableLookupAlias<asm # ".16b",
5749 !cast<Instruction>(NAME#"v16i8Three"),
5750 V128, VecListThree128>;
5751 def : SIMDTableLookupAlias<asm # ".16b",
5752 !cast<Instruction>(NAME#"v16i8Four"),
5753 V128, VecListFour128>;
5754}
5755
5756
5757//----------------------------------------------------------------------------
5758// AdvSIMD scalar CPY
5759//----------------------------------------------------------------------------
5760let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5761class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5762 string kind, Operand idxtype>
5763 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5764 "{\t$dst, $src" # kind # "$idx" #
5765 "|\t$dst, $src$idx}", "", []>,
5766 Sched<[WriteV]> {
5767 bits<5> dst;
5768 bits<5> src;
5769 let Inst{31-21} = 0b01011110000;
5770 let Inst{15-10} = 0b000001;
5771 let Inst{9-5} = src;
5772 let Inst{4-0} = dst;
5773}
5774
5775class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5776 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5777 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5778 # "|\t$dst, $src$index}",
5779 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5780
5781
5782multiclass SIMDScalarCPY<string asm> {
5783 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5784 bits<4> idx;
5785 let Inst{20-17} = idx;
5786 let Inst{16} = 1;
5787 }
5788 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5789 bits<3> idx;
5790 let Inst{20-18} = idx;
5791 let Inst{17-16} = 0b10;
5792 }
5793 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5794 bits<2> idx;
5795 let Inst{20-19} = idx;
5796 let Inst{18-16} = 0b100;
5797 }
5798 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5799 bits<1> idx;
5800 let Inst{20} = idx;
5801 let Inst{19-16} = 0b1000;
5802 }
5803
5804 // 'DUP' mnemonic aliases.
5805 def : SIMDScalarCPYAlias<"dup", ".b",
5806 !cast<Instruction>(NAME#"i8"),
5807 FPR8, V128, VectorIndexB>;
5808 def : SIMDScalarCPYAlias<"dup", ".h",
5809 !cast<Instruction>(NAME#"i16"),
5810 FPR16, V128, VectorIndexH>;
5811 def : SIMDScalarCPYAlias<"dup", ".s",
5812 !cast<Instruction>(NAME#"i32"),
5813 FPR32, V128, VectorIndexS>;
5814 def : SIMDScalarCPYAlias<"dup", ".d",
5815 !cast<Instruction>(NAME#"i64"),
5816 FPR64, V128, VectorIndexD>;
5817}
5818
5819//----------------------------------------------------------------------------
5820// AdvSIMD modified immediate instructions
5821//----------------------------------------------------------------------------
5822
5823class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5824 string asm, string op_string,
5825 string cstr, list<dag> pattern>
5826 : I<oops, iops, asm, op_string, cstr, pattern>,
5827 Sched<[WriteV]> {
5828 bits<5> Rd;
5829 bits<8> imm8;
5830 let Inst{31} = 0;
5831 let Inst{30} = Q;
5832 let Inst{29} = op;
5833 let Inst{28-19} = 0b0111100000;
5834 let Inst{18-16} = imm8{7-5};
5835 let Inst{11-10} = 0b01;
5836 let Inst{9-5} = imm8{4-0};
5837 let Inst{4-0} = Rd;
5838}
5839
5840class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5841 Operand immtype, dag opt_shift_iop,
5842 string opt_shift, string asm, string kind,
5843 list<dag> pattern>
5844 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5845 !con((ins immtype:$imm8), opt_shift_iop), asm,
5846 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5847 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5848 "", pattern> {
5849 let DecoderMethod = "DecodeModImmInstruction";
5850}
5851
5852class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5853 Operand immtype, dag opt_shift_iop,
5854 string opt_shift, string asm, string kind,
5855 list<dag> pattern>
5856 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5857 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5858 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5859 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5860 "$Rd = $dst", pattern> {
5861 let DecoderMethod = "DecodeModImmTiedInstruction";
5862}
5863
5864class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5865 RegisterOperand vectype, string asm,
5866 string kind, list<dag> pattern>
5867 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5868 (ins logical_vec_shift:$shift),
5869 "$shift", asm, kind, pattern> {
5870 bits<2> shift;
5871 let Inst{15} = b15_b12{1};
5872 let Inst{14-13} = shift;
5873 let Inst{12} = b15_b12{0};
5874}
5875
5876class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5877 RegisterOperand vectype, string asm,
5878 string kind, list<dag> pattern>
5879 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5880 (ins logical_vec_shift:$shift),
5881 "$shift", asm, kind, pattern> {
5882 bits<2> shift;
5883 let Inst{15} = b15_b12{1};
5884 let Inst{14-13} = shift;
5885 let Inst{12} = b15_b12{0};
5886}
5887
5888
5889class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5890 RegisterOperand vectype, string asm,
5891 string kind, list<dag> pattern>
5892 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5893 (ins logical_vec_hw_shift:$shift),
5894 "$shift", asm, kind, pattern> {
5895 bits<2> shift;
5896 let Inst{15} = b15_b12{1};
5897 let Inst{14} = 0;
5898 let Inst{13} = shift{0};
5899 let Inst{12} = b15_b12{0};
5900}
5901
5902class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5903 RegisterOperand vectype, string asm,
5904 string kind, list<dag> pattern>
5905 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5906 (ins logical_vec_hw_shift:$shift),
5907 "$shift", asm, kind, pattern> {
5908 bits<2> shift;
5909 let Inst{15} = b15_b12{1};
5910 let Inst{14} = 0;
5911 let Inst{13} = shift{0};
5912 let Inst{12} = b15_b12{0};
5913}
5914
5915multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5916 string asm> {
5917 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5918 asm, ".4h", []>;
5919 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5920 asm, ".8h", []>;
5921
5922 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5923 asm, ".2s", []>;
5924 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5925 asm, ".4s", []>;
5926}
5927
5928multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5929 bits<2> w_cmode, string asm,
5930 SDNode OpNode> {
5931 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5932 asm, ".4h",
5933 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5934 imm0_255:$imm8,
5935 (i32 imm:$shift)))]>;
5936 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5937 asm, ".8h",
5938 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5939 imm0_255:$imm8,
5940 (i32 imm:$shift)))]>;
5941
5942 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5943 asm, ".2s",
5944 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5945 imm0_255:$imm8,
5946 (i32 imm:$shift)))]>;
5947 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5948 asm, ".4s",
5949 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5950 imm0_255:$imm8,
5951 (i32 imm:$shift)))]>;
5952}
5953
5954class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5955 RegisterOperand vectype, string asm,
5956 string kind, list<dag> pattern>
5957 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5958 (ins move_vec_shift:$shift),
5959 "$shift", asm, kind, pattern> {
5960 bits<1> shift;
5961 let Inst{15-13} = cmode{3-1};
5962 let Inst{12} = shift;
5963}
5964
5965class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5966 RegisterOperand vectype,
5967 Operand imm_type, string asm,
5968 string kind, list<dag> pattern>
5969 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5970 asm, kind, pattern> {
5971 let Inst{15-12} = cmode;
5972}
5973
5974class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5975 list<dag> pattern>
5976 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5977 "\t$Rd, $imm8", "", pattern> {
5978 let Inst{15-12} = cmode;
5979 let DecoderMethod = "DecodeModImmInstruction";
5980}
5981
5982//----------------------------------------------------------------------------
5983// AdvSIMD indexed element
5984//----------------------------------------------------------------------------
5985
5986let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5987class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5988 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5989 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5990 string apple_kind, string dst_kind, string lhs_kind,
5991 string rhs_kind, list<dag> pattern>
5992 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5993 asm,
5994 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5995 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5996 Sched<[WriteV]> {
5997 bits<5> Rd;
5998 bits<5> Rn;
5999 bits<5> Rm;
6000
6001 let Inst{31} = 0;
6002 let Inst{30} = Q;
6003 let Inst{29} = U;
6004 let Inst{28} = Scalar;
6005 let Inst{27-24} = 0b1111;
6006 let Inst{23-22} = size;
6007 // Bit 21 must be set by the derived class.
6008 let Inst{20-16} = Rm;
6009 let Inst{15-12} = opc;
6010 // Bit 11 must be set by the derived class.
6011 let Inst{10} = 0;
6012 let Inst{9-5} = Rn;
6013 let Inst{4-0} = Rd;
6014}
6015
6016let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6017class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6018 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6019 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6020 string apple_kind, string dst_kind, string lhs_kind,
6021 string rhs_kind, list<dag> pattern>
6022 : I<(outs dst_reg:$dst),
6023 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6024 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6025 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6026 Sched<[WriteV]> {
6027 bits<5> Rd;
6028 bits<5> Rn;
6029 bits<5> Rm;
6030
6031 let Inst{31} = 0;
6032 let Inst{30} = Q;
6033 let Inst{29} = U;
6034 let Inst{28} = Scalar;
6035 let Inst{27-24} = 0b1111;
6036 let Inst{23-22} = size;
6037 // Bit 21 must be set by the derived class.
6038 let Inst{20-16} = Rm;
6039 let Inst{15-12} = opc;
6040 // Bit 11 must be set by the derived class.
6041 let Inst{10} = 0;
6042 let Inst{9-5} = Rn;
6043 let Inst{4-0} = Rd;
6044}
6045
6046multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6047 SDPatternOperator OpNode> {
6048 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6049 V64, V64,
6050 V128, VectorIndexS,
6051 asm, ".2s", ".2s", ".2s", ".s",
6052 [(set (v2f32 V64:$Rd),
6053 (OpNode (v2f32 V64:$Rn),
6054 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6055 bits<2> idx;
6056 let Inst{11} = idx{1};
6057 let Inst{21} = idx{0};
6058 }
6059
6060 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6061 V128, V128,
6062 V128, VectorIndexS,
6063 asm, ".4s", ".4s", ".4s", ".s",
6064 [(set (v4f32 V128:$Rd),
6065 (OpNode (v4f32 V128:$Rn),
6066 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6067 bits<2> idx;
6068 let Inst{11} = idx{1};
6069 let Inst{21} = idx{0};
6070 }
6071
6072 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6073 V128, V128,
6074 V128, VectorIndexD,
6075 asm, ".2d", ".2d", ".2d", ".d",
6076 [(set (v2f64 V128:$Rd),
6077 (OpNode (v2f64 V128:$Rn),
6078 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6079 bits<1> idx;
6080 let Inst{11} = idx{0};
6081 let Inst{21} = 0;
6082 }
6083
6084 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6085 FPR32Op, FPR32Op, V128, VectorIndexS,
6086 asm, ".s", "", "", ".s",
6087 [(set (f32 FPR32Op:$Rd),
6088 (OpNode (f32 FPR32Op:$Rn),
6089 (f32 (vector_extract (v4f32 V128:$Rm),
6090 VectorIndexS:$idx))))]> {
6091 bits<2> idx;
6092 let Inst{11} = idx{1};
6093 let Inst{21} = idx{0};
6094 }
6095
6096 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6097 FPR64Op, FPR64Op, V128, VectorIndexD,
6098 asm, ".d", "", "", ".d",
6099 [(set (f64 FPR64Op:$Rd),
6100 (OpNode (f64 FPR64Op:$Rn),
6101 (f64 (vector_extract (v2f64 V128:$Rm),
6102 VectorIndexD:$idx))))]> {
6103 bits<1> idx;
6104 let Inst{11} = idx{0};
6105 let Inst{21} = 0;
6106 }
6107}
6108
6109multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6110 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6111 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6112 (ARM64duplane32 (v4f32 V128:$Rm),
6113 VectorIndexS:$idx))),
6114 (!cast<Instruction>(INST # v2i32_indexed)
6115 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6116 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6117 (ARM64dup (f32 FPR32Op:$Rm)))),
6118 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6119 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6120
6121
6122 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6123 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6124 (ARM64duplane32 (v4f32 V128:$Rm),
6125 VectorIndexS:$idx))),
6126 (!cast<Instruction>(INST # "v4i32_indexed")
6127 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6128 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6129 (ARM64dup (f32 FPR32Op:$Rm)))),
6130 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6131 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6132
6133 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6134 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6135 (ARM64duplane64 (v2f64 V128:$Rm),
6136 VectorIndexD:$idx))),
6137 (!cast<Instruction>(INST # "v2i64_indexed")
6138 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6139 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6140 (ARM64dup (f64 FPR64Op:$Rm)))),
6141 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6142 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6143
6144 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6145 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6146 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6147 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6148 V128:$Rm, VectorIndexS:$idx)>;
6149 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6150 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6151 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6152 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6153
6154 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6155 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6156 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6157 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6158 V128:$Rm, VectorIndexD:$idx)>;
6159}
6160
6161multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6162 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6163 V128, VectorIndexS,
6164 asm, ".2s", ".2s", ".2s", ".s", []> {
6165 bits<2> idx;
6166 let Inst{11} = idx{1};
6167 let Inst{21} = idx{0};
6168 }
6169
6170 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6171 V128, V128,
6172 V128, VectorIndexS,
6173 asm, ".4s", ".4s", ".4s", ".s", []> {
6174 bits<2> idx;
6175 let Inst{11} = idx{1};
6176 let Inst{21} = idx{0};
6177 }
6178
6179 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6180 V128, V128,
6181 V128, VectorIndexD,
6182 asm, ".2d", ".2d", ".2d", ".d", []> {
6183 bits<1> idx;
6184 let Inst{11} = idx{0};
6185 let Inst{21} = 0;
6186 }
6187
6188
6189 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6190 FPR32Op, FPR32Op, V128, VectorIndexS,
6191 asm, ".s", "", "", ".s", []> {
6192 bits<2> idx;
6193 let Inst{11} = idx{1};
6194 let Inst{21} = idx{0};
6195 }
6196
6197 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6198 FPR64Op, FPR64Op, V128, VectorIndexD,
6199 asm, ".d", "", "", ".d", []> {
6200 bits<1> idx;
6201 let Inst{11} = idx{0};
6202 let Inst{21} = 0;
6203 }
6204}
6205
6206multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6207 SDPatternOperator OpNode> {
6208 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6209 V128_lo, VectorIndexH,
6210 asm, ".4h", ".4h", ".4h", ".h",
6211 [(set (v4i16 V64:$Rd),
6212 (OpNode (v4i16 V64:$Rn),
6213 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6214 bits<3> idx;
6215 let Inst{11} = idx{2};
6216 let Inst{21} = idx{1};
6217 let Inst{20} = idx{0};
6218 }
6219
6220 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6221 V128, V128,
6222 V128_lo, VectorIndexH,
6223 asm, ".8h", ".8h", ".8h", ".h",
6224 [(set (v8i16 V128:$Rd),
6225 (OpNode (v8i16 V128:$Rn),
6226 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6227 bits<3> idx;
6228 let Inst{11} = idx{2};
6229 let Inst{21} = idx{1};
6230 let Inst{20} = idx{0};
6231 }
6232
6233 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6234 V64, V64,
6235 V128, VectorIndexS,
6236 asm, ".2s", ".2s", ".2s", ".s",
6237 [(set (v2i32 V64:$Rd),
6238 (OpNode (v2i32 V64:$Rn),
6239 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6240 bits<2> idx;
6241 let Inst{11} = idx{1};
6242 let Inst{21} = idx{0};
6243 }
6244
6245 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6246 V128, V128,
6247 V128, VectorIndexS,
6248 asm, ".4s", ".4s", ".4s", ".s",
6249 [(set (v4i32 V128:$Rd),
6250 (OpNode (v4i32 V128:$Rn),
6251 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6252 bits<2> idx;
6253 let Inst{11} = idx{1};
6254 let Inst{21} = idx{0};
6255 }
6256
6257 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6258 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6259 asm, ".h", "", "", ".h", []> {
6260 bits<3> idx;
6261 let Inst{11} = idx{2};
6262 let Inst{21} = idx{1};
6263 let Inst{20} = idx{0};
6264 }
6265
6266 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6267 FPR32Op, FPR32Op, V128, VectorIndexS,
6268 asm, ".s", "", "", ".s",
6269 [(set (i32 FPR32Op:$Rd),
6270 (OpNode FPR32Op:$Rn,
6271 (i32 (vector_extract (v4i32 V128:$Rm),
6272 VectorIndexS:$idx))))]> {
6273 bits<2> idx;
6274 let Inst{11} = idx{1};
6275 let Inst{21} = idx{0};
6276 }
6277}
6278
6279multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6280 SDPatternOperator OpNode> {
6281 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6282 V64, V64,
6283 V128_lo, VectorIndexH,
6284 asm, ".4h", ".4h", ".4h", ".h",
6285 [(set (v4i16 V64:$Rd),
6286 (OpNode (v4i16 V64:$Rn),
6287 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6288 bits<3> idx;
6289 let Inst{11} = idx{2};
6290 let Inst{21} = idx{1};
6291 let Inst{20} = idx{0};
6292 }
6293
6294 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6295 V128, V128,
6296 V128_lo, VectorIndexH,
6297 asm, ".8h", ".8h", ".8h", ".h",
6298 [(set (v8i16 V128:$Rd),
6299 (OpNode (v8i16 V128:$Rn),
6300 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6301 bits<3> idx;
6302 let Inst{11} = idx{2};
6303 let Inst{21} = idx{1};
6304 let Inst{20} = idx{0};
6305 }
6306
6307 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6308 V64, V64,
6309 V128, VectorIndexS,
6310 asm, ".2s", ".2s", ".2s", ".s",
6311 [(set (v2i32 V64:$Rd),
6312 (OpNode (v2i32 V64:$Rn),
6313 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6314 bits<2> idx;
6315 let Inst{11} = idx{1};
6316 let Inst{21} = idx{0};
6317 }
6318
6319 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6320 V128, V128,
6321 V128, VectorIndexS,
6322 asm, ".4s", ".4s", ".4s", ".s",
6323 [(set (v4i32 V128:$Rd),
6324 (OpNode (v4i32 V128:$Rn),
6325 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6326 bits<2> idx;
6327 let Inst{11} = idx{1};
6328 let Inst{21} = idx{0};
6329 }
6330}
6331
6332multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6333 SDPatternOperator OpNode> {
6334 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6335 V128_lo, VectorIndexH,
6336 asm, ".4h", ".4h", ".4h", ".h",
6337 [(set (v4i16 V64:$dst),
6338 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6339 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6340 bits<3> idx;
6341 let Inst{11} = idx{2};
6342 let Inst{21} = idx{1};
6343 let Inst{20} = idx{0};
6344 }
6345
6346 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6347 V128, V128,
6348 V128_lo, VectorIndexH,
6349 asm, ".8h", ".8h", ".8h", ".h",
6350 [(set (v8i16 V128:$dst),
6351 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6352 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6353 bits<3> idx;
6354 let Inst{11} = idx{2};
6355 let Inst{21} = idx{1};
6356 let Inst{20} = idx{0};
6357 }
6358
6359 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6360 V64, V64,
6361 V128, VectorIndexS,
6362 asm, ".2s", ".2s", ".2s", ".s",
6363 [(set (v2i32 V64:$dst),
6364 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6365 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6366 bits<2> idx;
6367 let Inst{11} = idx{1};
6368 let Inst{21} = idx{0};
6369 }
6370
6371 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6372 V128, V128,
6373 V128, VectorIndexS,
6374 asm, ".4s", ".4s", ".4s", ".s",
6375 [(set (v4i32 V128:$dst),
6376 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6377 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6378 bits<2> idx;
6379 let Inst{11} = idx{1};
6380 let Inst{21} = idx{0};
6381 }
6382}
6383
6384multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6385 SDPatternOperator OpNode> {
6386 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6387 V128, V64,
6388 V128_lo, VectorIndexH,
6389 asm, ".4s", ".4s", ".4h", ".h",
6390 [(set (v4i32 V128:$Rd),
6391 (OpNode (v4i16 V64:$Rn),
6392 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6393 bits<3> idx;
6394 let Inst{11} = idx{2};
6395 let Inst{21} = idx{1};
6396 let Inst{20} = idx{0};
6397 }
6398
6399 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6400 V128, V128,
6401 V128_lo, VectorIndexH,
6402 asm#"2", ".4s", ".4s", ".8h", ".h",
6403 [(set (v4i32 V128:$Rd),
6404 (OpNode (extract_high_v8i16 V128:$Rn),
6405 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6406 VectorIndexH:$idx))))]> {
6407
6408 bits<3> idx;
6409 let Inst{11} = idx{2};
6410 let Inst{21} = idx{1};
6411 let Inst{20} = idx{0};
6412 }
6413
6414 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6415 V128, V64,
6416 V128, VectorIndexS,
6417 asm, ".2d", ".2d", ".2s", ".s",
6418 [(set (v2i64 V128:$Rd),
6419 (OpNode (v2i32 V64:$Rn),
6420 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6421 bits<2> idx;
6422 let Inst{11} = idx{1};
6423 let Inst{21} = idx{0};
6424 }
6425
6426 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6427 V128, V128,
6428 V128, VectorIndexS,
6429 asm#"2", ".2d", ".2d", ".4s", ".s",
6430 [(set (v2i64 V128:$Rd),
6431 (OpNode (extract_high_v4i32 V128:$Rn),
6432 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6433 VectorIndexS:$idx))))]> {
6434 bits<2> idx;
6435 let Inst{11} = idx{1};
6436 let Inst{21} = idx{0};
6437 }
6438
6439 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6440 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6441 asm, ".h", "", "", ".h", []> {
6442 bits<3> idx;
6443 let Inst{11} = idx{2};
6444 let Inst{21} = idx{1};
6445 let Inst{20} = idx{0};
6446 }
6447
6448 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6449 FPR64Op, FPR32Op, V128, VectorIndexS,
6450 asm, ".s", "", "", ".s", []> {
6451 bits<2> idx;
6452 let Inst{11} = idx{1};
6453 let Inst{21} = idx{0};
6454 }
6455}
6456
6457multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6458 SDPatternOperator Accum> {
6459 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6460 V128, V64,
6461 V128_lo, VectorIndexH,
6462 asm, ".4s", ".4s", ".4h", ".h",
6463 [(set (v4i32 V128:$dst),
6464 (Accum (v4i32 V128:$Rd),
6465 (v4i32 (int_arm64_neon_sqdmull
6466 (v4i16 V64:$Rn),
6467 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6468 VectorIndexH:$idx))))))]> {
6469 bits<3> idx;
6470 let Inst{11} = idx{2};
6471 let Inst{21} = idx{1};
6472 let Inst{20} = idx{0};
6473 }
6474
6475 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6476 // intermediate EXTRACT_SUBREG would be untyped.
6477 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6478 (i32 (vector_extract (v4i32
6479 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6480 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6481 VectorIndexH:$idx)))),
6482 (i64 0))))),
6483 (EXTRACT_SUBREG
6484 (!cast<Instruction>(NAME # v4i16_indexed)
6485 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6486 V128_lo:$Rm, VectorIndexH:$idx),
6487 ssub)>;
6488
6489 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6490 V128, V128,
6491 V128_lo, VectorIndexH,
6492 asm#"2", ".4s", ".4s", ".8h", ".h",
6493 [(set (v4i32 V128:$dst),
6494 (Accum (v4i32 V128:$Rd),
6495 (v4i32 (int_arm64_neon_sqdmull
6496 (extract_high_v8i16 V128:$Rn),
6497 (extract_high_v8i16
6498 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6499 VectorIndexH:$idx))))))]> {
6500 bits<3> idx;
6501 let Inst{11} = idx{2};
6502 let Inst{21} = idx{1};
6503 let Inst{20} = idx{0};
6504 }
6505
6506 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6507 V128, V64,
6508 V128, VectorIndexS,
6509 asm, ".2d", ".2d", ".2s", ".s",
6510 [(set (v2i64 V128:$dst),
6511 (Accum (v2i64 V128:$Rd),
6512 (v2i64 (int_arm64_neon_sqdmull
6513 (v2i32 V64:$Rn),
6514 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6515 VectorIndexS:$idx))))))]> {
6516 bits<2> idx;
6517 let Inst{11} = idx{1};
6518 let Inst{21} = idx{0};
6519 }
6520
6521 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6522 V128, V128,
6523 V128, VectorIndexS,
6524 asm#"2", ".2d", ".2d", ".4s", ".s",
6525 [(set (v2i64 V128:$dst),
6526 (Accum (v2i64 V128:$Rd),
6527 (v2i64 (int_arm64_neon_sqdmull
6528 (extract_high_v4i32 V128:$Rn),
6529 (extract_high_v4i32
6530 (ARM64duplane32 (v4i32 V128:$Rm),
6531 VectorIndexS:$idx))))))]> {
6532 bits<2> idx;
6533 let Inst{11} = idx{1};
6534 let Inst{21} = idx{0};
6535 }
6536
6537 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6538 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6539 asm, ".h", "", "", ".h", []> {
6540 bits<3> idx;
6541 let Inst{11} = idx{2};
6542 let Inst{21} = idx{1};
6543 let Inst{20} = idx{0};
6544 }
6545
6546
6547 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6548 FPR64Op, FPR32Op, V128, VectorIndexS,
6549 asm, ".s", "", "", ".s",
6550 [(set (i64 FPR64Op:$dst),
6551 (Accum (i64 FPR64Op:$Rd),
6552 (i64 (int_arm64_neon_sqdmulls_scalar
6553 (i32 FPR32Op:$Rn),
6554 (i32 (vector_extract (v4i32 V128:$Rm),
6555 VectorIndexS:$idx))))))]> {
6556
6557 bits<2> idx;
6558 let Inst{11} = idx{1};
6559 let Inst{21} = idx{0};
6560 }
6561}
6562
6563multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6564 SDPatternOperator OpNode> {
6565 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6566 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6567 V128, V64,
6568 V128_lo, VectorIndexH,
6569 asm, ".4s", ".4s", ".4h", ".h",
6570 [(set (v4i32 V128:$Rd),
6571 (OpNode (v4i16 V64:$Rn),
6572 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6573 bits<3> idx;
6574 let Inst{11} = idx{2};
6575 let Inst{21} = idx{1};
6576 let Inst{20} = idx{0};
6577 }
6578
6579 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6580 V128, V128,
6581 V128_lo, VectorIndexH,
6582 asm#"2", ".4s", ".4s", ".8h", ".h",
6583 [(set (v4i32 V128:$Rd),
6584 (OpNode (extract_high_v8i16 V128:$Rn),
6585 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6586 VectorIndexH:$idx))))]> {
6587
6588 bits<3> idx;
6589 let Inst{11} = idx{2};
6590 let Inst{21} = idx{1};
6591 let Inst{20} = idx{0};
6592 }
6593
6594 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6595 V128, V64,
6596 V128, VectorIndexS,
6597 asm, ".2d", ".2d", ".2s", ".s",
6598 [(set (v2i64 V128:$Rd),
6599 (OpNode (v2i32 V64:$Rn),
6600 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6601 bits<2> idx;
6602 let Inst{11} = idx{1};
6603 let Inst{21} = idx{0};
6604 }
6605
6606 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6607 V128, V128,
6608 V128, VectorIndexS,
6609 asm#"2", ".2d", ".2d", ".4s", ".s",
6610 [(set (v2i64 V128:$Rd),
6611 (OpNode (extract_high_v4i32 V128:$Rn),
6612 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6613 VectorIndexS:$idx))))]> {
6614 bits<2> idx;
6615 let Inst{11} = idx{1};
6616 let Inst{21} = idx{0};
6617 }
6618 }
6619}
6620
6621multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6622 SDPatternOperator OpNode> {
6623 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6624 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6625 V128, V64,
6626 V128_lo, VectorIndexH,
6627 asm, ".4s", ".4s", ".4h", ".h",
6628 [(set (v4i32 V128:$dst),
6629 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6630 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6631 bits<3> idx;
6632 let Inst{11} = idx{2};
6633 let Inst{21} = idx{1};
6634 let Inst{20} = idx{0};
6635 }
6636
6637 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6638 V128, V128,
6639 V128_lo, VectorIndexH,
6640 asm#"2", ".4s", ".4s", ".8h", ".h",
6641 [(set (v4i32 V128:$dst),
6642 (OpNode (v4i32 V128:$Rd),
6643 (extract_high_v8i16 V128:$Rn),
6644 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6645 VectorIndexH:$idx))))]> {
6646 bits<3> idx;
6647 let Inst{11} = idx{2};
6648 let Inst{21} = idx{1};
6649 let Inst{20} = idx{0};
6650 }
6651
6652 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6653 V128, V64,
6654 V128, VectorIndexS,
6655 asm, ".2d", ".2d", ".2s", ".s",
6656 [(set (v2i64 V128:$dst),
6657 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6658 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6659 bits<2> idx;
6660 let Inst{11} = idx{1};
6661 let Inst{21} = idx{0};
6662 }
6663
6664 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6665 V128, V128,
6666 V128, VectorIndexS,
6667 asm#"2", ".2d", ".2d", ".4s", ".s",
6668 [(set (v2i64 V128:$dst),
6669 (OpNode (v2i64 V128:$Rd),
6670 (extract_high_v4i32 V128:$Rn),
6671 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6672 VectorIndexS:$idx))))]> {
6673 bits<2> idx;
6674 let Inst{11} = idx{1};
6675 let Inst{21} = idx{0};
6676 }
6677 }
6678}
6679
6680//----------------------------------------------------------------------------
6681// AdvSIMD scalar shift by immediate
6682//----------------------------------------------------------------------------
6683
6684let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6685class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6686 RegisterClass regtype1, RegisterClass regtype2,
6687 Operand immtype, string asm, list<dag> pattern>
6688 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6689 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6690 Sched<[WriteV]> {
6691 bits<5> Rd;
6692 bits<5> Rn;
6693 bits<7> imm;
6694 let Inst{31-30} = 0b01;
6695 let Inst{29} = U;
6696 let Inst{28-23} = 0b111110;
6697 let Inst{22-16} = fixed_imm;
6698 let Inst{15-11} = opc;
6699 let Inst{10} = 1;
6700 let Inst{9-5} = Rn;
6701 let Inst{4-0} = Rd;
6702}
6703
6704let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6705class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6706 RegisterClass regtype1, RegisterClass regtype2,
6707 Operand immtype, string asm, list<dag> pattern>
6708 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6709 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6710 Sched<[WriteV]> {
6711 bits<5> Rd;
6712 bits<5> Rn;
6713 bits<7> imm;
6714 let Inst{31-30} = 0b01;
6715 let Inst{29} = U;
6716 let Inst{28-23} = 0b111110;
6717 let Inst{22-16} = fixed_imm;
6718 let Inst{15-11} = opc;
6719 let Inst{10} = 1;
6720 let Inst{9-5} = Rn;
6721 let Inst{4-0} = Rd;
6722}
6723
6724
6725multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6726 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6727 FPR32, FPR32, vecshiftR32, asm, []> {
6728 let Inst{20-16} = imm{4-0};
6729 }
6730
6731 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6732 FPR64, FPR64, vecshiftR64, asm, []> {
6733 let Inst{21-16} = imm{5-0};
6734 }
6735}
6736
6737multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6738 SDPatternOperator OpNode> {
6739 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6740 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006741 [(set (i64 FPR64:$Rd),
6742 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006743 let Inst{21-16} = imm{5-0};
6744 }
Tim Northover5081cd02014-03-31 15:46:46 +00006745
6746 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6747 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006748}
6749
Tim Northover00ed9962014-03-29 10:18:08 +00006750multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6751 SDPatternOperator OpNode = null_frag> {
6752 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6753 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006754 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6755 (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006756 let Inst{21-16} = imm{5-0};
6757 }
Tim Northover5081cd02014-03-31 15:46:46 +00006758
6759 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6760 (i32 vecshiftR64:$imm))),
6761 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6762 vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006763}
6764
6765multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6766 SDPatternOperator OpNode> {
6767 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6768 FPR64, FPR64, vecshiftL64, asm,
6769 [(set (v1i64 FPR64:$Rd),
6770 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6771 let Inst{21-16} = imm{5-0};
6772 }
6773}
6774
6775let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6776multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6777 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6778 FPR64, FPR64, vecshiftL64, asm, []> {
6779 let Inst{21-16} = imm{5-0};
6780 }
6781}
6782
6783let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6784multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6785 SDPatternOperator OpNode = null_frag> {
6786 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6787 FPR8, FPR16, vecshiftR8, asm, []> {
6788 let Inst{18-16} = imm{2-0};
6789 }
6790
6791 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6792 FPR16, FPR32, vecshiftR16, asm, []> {
6793 let Inst{19-16} = imm{3-0};
6794 }
6795
6796 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6797 FPR32, FPR64, vecshiftR32, asm,
6798 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6799 let Inst{20-16} = imm{4-0};
6800 }
6801}
6802
6803multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6804 SDPatternOperator OpNode> {
6805 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6806 FPR8, FPR8, vecshiftL8, asm, []> {
6807 let Inst{18-16} = imm{2-0};
6808 }
6809
6810 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6811 FPR16, FPR16, vecshiftL16, asm, []> {
6812 let Inst{19-16} = imm{3-0};
6813 }
6814
6815 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6816 FPR32, FPR32, vecshiftL32, asm,
6817 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6818 let Inst{20-16} = imm{4-0};
6819 }
6820
6821 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6822 FPR64, FPR64, vecshiftL64, asm,
6823 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6824 (i32 vecshiftL64:$imm)))]> {
6825 let Inst{21-16} = imm{5-0};
6826 }
6827}
6828
6829multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6830 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6831 FPR8, FPR8, vecshiftR8, asm, []> {
6832 let Inst{18-16} = imm{2-0};
6833 }
6834
6835 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6836 FPR16, FPR16, vecshiftR16, asm, []> {
6837 let Inst{19-16} = imm{3-0};
6838 }
6839
6840 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6841 FPR32, FPR32, vecshiftR32, asm, []> {
6842 let Inst{20-16} = imm{4-0};
6843 }
6844
6845 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6846 FPR64, FPR64, vecshiftR64, asm, []> {
6847 let Inst{21-16} = imm{5-0};
6848 }
6849}
6850
6851//----------------------------------------------------------------------------
6852// AdvSIMD vector x indexed element
6853//----------------------------------------------------------------------------
6854
6855let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6856class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6857 RegisterOperand dst_reg, RegisterOperand src_reg,
6858 Operand immtype,
6859 string asm, string dst_kind, string src_kind,
6860 list<dag> pattern>
6861 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6862 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6863 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6864 Sched<[WriteV]> {
6865 bits<5> Rd;
6866 bits<5> Rn;
6867 let Inst{31} = 0;
6868 let Inst{30} = Q;
6869 let Inst{29} = U;
6870 let Inst{28-23} = 0b011110;
6871 let Inst{22-16} = fixed_imm;
6872 let Inst{15-11} = opc;
6873 let Inst{10} = 1;
6874 let Inst{9-5} = Rn;
6875 let Inst{4-0} = Rd;
6876}
6877
6878let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6879class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6880 RegisterOperand vectype1, RegisterOperand vectype2,
6881 Operand immtype,
6882 string asm, string dst_kind, string src_kind,
6883 list<dag> pattern>
6884 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6885 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6886 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6887 Sched<[WriteV]> {
6888 bits<5> Rd;
6889 bits<5> Rn;
6890 let Inst{31} = 0;
6891 let Inst{30} = Q;
6892 let Inst{29} = U;
6893 let Inst{28-23} = 0b011110;
6894 let Inst{22-16} = fixed_imm;
6895 let Inst{15-11} = opc;
6896 let Inst{10} = 1;
6897 let Inst{9-5} = Rn;
6898 let Inst{4-0} = Rd;
6899}
6900
6901multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6902 Intrinsic OpNode> {
6903 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6904 V64, V64, vecshiftR32,
6905 asm, ".2s", ".2s",
6906 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6907 bits<5> imm;
6908 let Inst{20-16} = imm;
6909 }
6910
6911 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6912 V128, V128, vecshiftR32,
6913 asm, ".4s", ".4s",
6914 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6915 bits<5> imm;
6916 let Inst{20-16} = imm;
6917 }
6918
6919 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6920 V128, V128, vecshiftR64,
6921 asm, ".2d", ".2d",
6922 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6923 bits<6> imm;
6924 let Inst{21-16} = imm;
6925 }
6926}
6927
6928multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6929 Intrinsic OpNode> {
6930 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6931 V64, V64, vecshiftR32,
6932 asm, ".2s", ".2s",
6933 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6934 bits<5> imm;
6935 let Inst{20-16} = imm;
6936 }
6937
6938 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6939 V128, V128, vecshiftR32,
6940 asm, ".4s", ".4s",
6941 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6942 bits<5> imm;
6943 let Inst{20-16} = imm;
6944 }
6945
6946 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6947 V128, V128, vecshiftR64,
6948 asm, ".2d", ".2d",
6949 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6950 bits<6> imm;
6951 let Inst{21-16} = imm;
6952 }
6953}
6954
6955multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6956 SDPatternOperator OpNode> {
6957 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6958 V64, V128, vecshiftR16Narrow,
6959 asm, ".8b", ".8h",
6960 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6961 bits<3> imm;
6962 let Inst{18-16} = imm;
6963 }
6964
6965 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6966 V128, V128, vecshiftR16Narrow,
6967 asm#"2", ".16b", ".8h", []> {
6968 bits<3> imm;
6969 let Inst{18-16} = imm;
6970 let hasSideEffects = 0;
6971 }
6972
6973 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6974 V64, V128, vecshiftR32Narrow,
6975 asm, ".4h", ".4s",
6976 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6977 bits<4> imm;
6978 let Inst{19-16} = imm;
6979 }
6980
6981 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6982 V128, V128, vecshiftR32Narrow,
6983 asm#"2", ".8h", ".4s", []> {
6984 bits<4> imm;
6985 let Inst{19-16} = imm;
6986 let hasSideEffects = 0;
6987 }
6988
6989 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6990 V64, V128, vecshiftR64Narrow,
6991 asm, ".2s", ".2d",
6992 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6993 bits<5> imm;
6994 let Inst{20-16} = imm;
6995 }
6996
6997 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6998 V128, V128, vecshiftR64Narrow,
6999 asm#"2", ".4s", ".2d", []> {
7000 bits<5> imm;
7001 let Inst{20-16} = imm;
7002 let hasSideEffects = 0;
7003 }
7004
7005 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7006 // themselves, so put them here instead.
7007
7008 // Patterns involving what's effectively an insert high and a normal
7009 // intrinsic, represented by CONCAT_VECTORS.
7010 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7011 vecshiftR16Narrow:$imm)),
7012 (!cast<Instruction>(NAME # "v16i8_shift")
7013 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7014 V128:$Rn, vecshiftR16Narrow:$imm)>;
7015 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7016 vecshiftR32Narrow:$imm)),
7017 (!cast<Instruction>(NAME # "v8i16_shift")
7018 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7019 V128:$Rn, vecshiftR32Narrow:$imm)>;
7020 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7021 vecshiftR64Narrow:$imm)),
7022 (!cast<Instruction>(NAME # "v4i32_shift")
7023 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7024 V128:$Rn, vecshiftR64Narrow:$imm)>;
7025}
7026
7027multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7028 SDPatternOperator OpNode> {
7029 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7030 V64, V64, vecshiftL8,
7031 asm, ".8b", ".8b",
7032 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7033 (i32 vecshiftL8:$imm)))]> {
7034 bits<3> imm;
7035 let Inst{18-16} = imm;
7036 }
7037
7038 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7039 V128, V128, vecshiftL8,
7040 asm, ".16b", ".16b",
7041 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7042 (i32 vecshiftL8:$imm)))]> {
7043 bits<3> imm;
7044 let Inst{18-16} = imm;
7045 }
7046
7047 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7048 V64, V64, vecshiftL16,
7049 asm, ".4h", ".4h",
7050 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7051 (i32 vecshiftL16:$imm)))]> {
7052 bits<4> imm;
7053 let Inst{19-16} = imm;
7054 }
7055
7056 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7057 V128, V128, vecshiftL16,
7058 asm, ".8h", ".8h",
7059 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7060 (i32 vecshiftL16:$imm)))]> {
7061 bits<4> imm;
7062 let Inst{19-16} = imm;
7063 }
7064
7065 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7066 V64, V64, vecshiftL32,
7067 asm, ".2s", ".2s",
7068 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7069 (i32 vecshiftL32:$imm)))]> {
7070 bits<5> imm;
7071 let Inst{20-16} = imm;
7072 }
7073
7074 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7075 V128, V128, vecshiftL32,
7076 asm, ".4s", ".4s",
7077 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7078 (i32 vecshiftL32:$imm)))]> {
7079 bits<5> imm;
7080 let Inst{20-16} = imm;
7081 }
7082
7083 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7084 V128, V128, vecshiftL64,
7085 asm, ".2d", ".2d",
7086 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7087 (i32 vecshiftL64:$imm)))]> {
7088 bits<6> imm;
7089 let Inst{21-16} = imm;
7090 }
7091}
7092
7093multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7094 SDPatternOperator OpNode> {
7095 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7096 V64, V64, vecshiftR8,
7097 asm, ".8b", ".8b",
7098 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7099 (i32 vecshiftR8:$imm)))]> {
7100 bits<3> imm;
7101 let Inst{18-16} = imm;
7102 }
7103
7104 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7105 V128, V128, vecshiftR8,
7106 asm, ".16b", ".16b",
7107 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7108 (i32 vecshiftR8:$imm)))]> {
7109 bits<3> imm;
7110 let Inst{18-16} = imm;
7111 }
7112
7113 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7114 V64, V64, vecshiftR16,
7115 asm, ".4h", ".4h",
7116 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7117 (i32 vecshiftR16:$imm)))]> {
7118 bits<4> imm;
7119 let Inst{19-16} = imm;
7120 }
7121
7122 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7123 V128, V128, vecshiftR16,
7124 asm, ".8h", ".8h",
7125 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7126 (i32 vecshiftR16:$imm)))]> {
7127 bits<4> imm;
7128 let Inst{19-16} = imm;
7129 }
7130
7131 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7132 V64, V64, vecshiftR32,
7133 asm, ".2s", ".2s",
7134 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7135 (i32 vecshiftR32:$imm)))]> {
7136 bits<5> imm;
7137 let Inst{20-16} = imm;
7138 }
7139
7140 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7141 V128, V128, vecshiftR32,
7142 asm, ".4s", ".4s",
7143 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7144 (i32 vecshiftR32:$imm)))]> {
7145 bits<5> imm;
7146 let Inst{20-16} = imm;
7147 }
7148
7149 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7150 V128, V128, vecshiftR64,
7151 asm, ".2d", ".2d",
7152 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7153 (i32 vecshiftR64:$imm)))]> {
7154 bits<6> imm;
7155 let Inst{21-16} = imm;
7156 }
7157}
7158
7159let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7160multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7161 SDPatternOperator OpNode = null_frag> {
7162 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7163 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7164 [(set (v8i8 V64:$dst),
7165 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7166 (i32 vecshiftR8:$imm)))]> {
7167 bits<3> imm;
7168 let Inst{18-16} = imm;
7169 }
7170
7171 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7172 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7173 [(set (v16i8 V128:$dst),
7174 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7175 (i32 vecshiftR8:$imm)))]> {
7176 bits<3> imm;
7177 let Inst{18-16} = imm;
7178 }
7179
7180 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7181 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7182 [(set (v4i16 V64:$dst),
7183 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7184 (i32 vecshiftR16:$imm)))]> {
7185 bits<4> imm;
7186 let Inst{19-16} = imm;
7187 }
7188
7189 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7190 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7191 [(set (v8i16 V128:$dst),
7192 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7193 (i32 vecshiftR16:$imm)))]> {
7194 bits<4> imm;
7195 let Inst{19-16} = imm;
7196 }
7197
7198 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7199 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7200 [(set (v2i32 V64:$dst),
7201 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7202 (i32 vecshiftR32:$imm)))]> {
7203 bits<5> imm;
7204 let Inst{20-16} = imm;
7205 }
7206
7207 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7208 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7209 [(set (v4i32 V128:$dst),
7210 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7211 (i32 vecshiftR32:$imm)))]> {
7212 bits<5> imm;
7213 let Inst{20-16} = imm;
7214 }
7215
7216 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7217 V128, V128, vecshiftR64,
7218 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7219 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7220 (i32 vecshiftR64:$imm)))]> {
7221 bits<6> imm;
7222 let Inst{21-16} = imm;
7223 }
7224}
7225
7226multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7227 SDPatternOperator OpNode = null_frag> {
7228 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7229 V64, V64, vecshiftL8,
7230 asm, ".8b", ".8b",
7231 [(set (v8i8 V64:$dst),
7232 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7233 (i32 vecshiftL8:$imm)))]> {
7234 bits<3> imm;
7235 let Inst{18-16} = imm;
7236 }
7237
7238 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7239 V128, V128, vecshiftL8,
7240 asm, ".16b", ".16b",
7241 [(set (v16i8 V128:$dst),
7242 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7243 (i32 vecshiftL8:$imm)))]> {
7244 bits<3> imm;
7245 let Inst{18-16} = imm;
7246 }
7247
7248 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7249 V64, V64, vecshiftL16,
7250 asm, ".4h", ".4h",
7251 [(set (v4i16 V64:$dst),
7252 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7253 (i32 vecshiftL16:$imm)))]> {
7254 bits<4> imm;
7255 let Inst{19-16} = imm;
7256 }
7257
7258 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7259 V128, V128, vecshiftL16,
7260 asm, ".8h", ".8h",
7261 [(set (v8i16 V128:$dst),
7262 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7263 (i32 vecshiftL16:$imm)))]> {
7264 bits<4> imm;
7265 let Inst{19-16} = imm;
7266 }
7267
7268 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7269 V64, V64, vecshiftL32,
7270 asm, ".2s", ".2s",
7271 [(set (v2i32 V64:$dst),
7272 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7273 (i32 vecshiftL32:$imm)))]> {
7274 bits<5> imm;
7275 let Inst{20-16} = imm;
7276 }
7277
7278 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7279 V128, V128, vecshiftL32,
7280 asm, ".4s", ".4s",
7281 [(set (v4i32 V128:$dst),
7282 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7283 (i32 vecshiftL32:$imm)))]> {
7284 bits<5> imm;
7285 let Inst{20-16} = imm;
7286 }
7287
7288 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7289 V128, V128, vecshiftL64,
7290 asm, ".2d", ".2d",
7291 [(set (v2i64 V128:$dst),
7292 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7293 (i32 vecshiftL64:$imm)))]> {
7294 bits<6> imm;
7295 let Inst{21-16} = imm;
7296 }
7297}
7298
7299multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7300 SDPatternOperator OpNode> {
7301 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7302 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7303 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7304 bits<3> imm;
7305 let Inst{18-16} = imm;
7306 }
7307
7308 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7309 V128, V128, vecshiftL8,
7310 asm#"2", ".8h", ".16b",
7311 [(set (v8i16 V128:$Rd),
7312 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7313 bits<3> imm;
7314 let Inst{18-16} = imm;
7315 }
7316
7317 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7318 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7319 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7320 bits<4> imm;
7321 let Inst{19-16} = imm;
7322 }
7323
7324 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7325 V128, V128, vecshiftL16,
7326 asm#"2", ".4s", ".8h",
7327 [(set (v4i32 V128:$Rd),
7328 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7329
7330 bits<4> imm;
7331 let Inst{19-16} = imm;
7332 }
7333
7334 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7335 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7336 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7337 bits<5> imm;
7338 let Inst{20-16} = imm;
7339 }
7340
7341 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7342 V128, V128, vecshiftL32,
7343 asm#"2", ".2d", ".4s",
7344 [(set (v2i64 V128:$Rd),
7345 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7346 bits<5> imm;
7347 let Inst{20-16} = imm;
7348 }
7349}
7350
7351
7352//---
7353// Vector load/store
7354//---
7355// SIMD ldX/stX no-index memory references don't allow the optional
7356// ", #0" constant and handle post-indexing explicitly, so we use
7357// a more specialized parse method for them. Otherwise, it's the same as
7358// the general am_noindex handling.
7359def MemorySIMDNoIndexOperand : AsmOperandClass {
7360 let Name = "MemorySIMDNoIndex";
7361 let ParserMethod = "tryParseNoIndexMemory";
7362}
7363def am_simdnoindex : Operand<i64>,
7364 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7365 let PrintMethod = "printAMNoIndex";
7366 let ParserMatchClass = MemorySIMDNoIndexOperand;
7367 let MIOperandInfo = (ops GPR64sp:$base);
7368 let DecoderMethod = "DecodeGPR64spRegisterClass";
7369}
7370
7371class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7372 string asm, dag oops, dag iops, list<dag> pattern>
7373 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7374 bits<5> Vt;
7375 bits<5> vaddr;
7376 let Inst{31} = 0;
7377 let Inst{30} = Q;
7378 let Inst{29-23} = 0b0011000;
7379 let Inst{22} = L;
7380 let Inst{21-16} = 0b000000;
7381 let Inst{15-12} = opcode;
7382 let Inst{11-10} = size;
7383 let Inst{9-5} = vaddr;
7384 let Inst{4-0} = Vt;
7385}
7386
7387class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7388 string asm, dag oops, dag iops>
7389 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7390 bits<5> Vt;
7391 bits<5> vaddr;
7392 bits<5> Xm;
7393 let Inst{31} = 0;
7394 let Inst{30} = Q;
7395 let Inst{29-23} = 0b0011001;
7396 let Inst{22} = L;
7397 let Inst{21} = 0;
7398 let Inst{20-16} = Xm;
7399 let Inst{15-12} = opcode;
7400 let Inst{11-10} = size;
7401 let Inst{9-5} = vaddr;
7402 let Inst{4-0} = Vt;
7403 let DecoderMethod = "DecodeSIMDLdStPost";
7404}
7405
7406// The immediate form of AdvSIMD post-indexed addressing is encoded with
7407// register post-index addressing from the zero register.
7408multiclass SIMDLdStAliases<string asm, string layout, string Count,
7409 int Offset, int Size> {
7410 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7411 // "ld1\t$Vt, $vaddr, #16"
7412 // may get mapped to
7413 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7414 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7415 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7416 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7417 am_simdnoindex:$vaddr, XZR), 1>;
7418
7419 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7420 // "ld1.8b\t$Vt, $vaddr, #16"
7421 // may get mapped to
7422 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7423 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7424 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7425 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7426 am_simdnoindex:$vaddr, XZR), 0>;
7427
7428 // E.g. "ld1.8b { v0, v1 }, [x1]"
7429 // "ld1\t$Vt, $vaddr"
7430 // may get mapped to
7431 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7432 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7433 (!cast<Instruction>(NAME # Count # "v" # layout)
7434 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7435 am_simdnoindex:$vaddr), 0>;
7436
7437 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7438 // "ld1\t$Vt, $vaddr, $Xm"
7439 // may get mapped to
7440 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7441 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7442 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7443 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7444 am_simdnoindex:$vaddr,
7445 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7446}
7447
7448multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7449 int Offset64, bits<4> opcode> {
7450 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7451 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7452 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7453 (ins am_simdnoindex:$vaddr), []>;
7454 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7455 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7456 (ins am_simdnoindex:$vaddr), []>;
7457 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7458 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7459 (ins am_simdnoindex:$vaddr), []>;
7460 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7461 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7462 (ins am_simdnoindex:$vaddr), []>;
7463 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7464 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7465 (ins am_simdnoindex:$vaddr), []>;
7466 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7467 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7468 (ins am_simdnoindex:$vaddr), []>;
7469 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7470 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7471 (ins am_simdnoindex:$vaddr), []>;
7472
7473
7474 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7475 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7476 (ins am_simdnoindex:$vaddr,
7477 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7478 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7479 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7480 (ins am_simdnoindex:$vaddr,
7481 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7482 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7483 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7484 (ins am_simdnoindex:$vaddr,
7485 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7486 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7487 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7488 (ins am_simdnoindex:$vaddr,
7489 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7490 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7491 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7492 (ins am_simdnoindex:$vaddr,
7493 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7494 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7495 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7496 (ins am_simdnoindex:$vaddr,
7497 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7498 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7499 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7500 (ins am_simdnoindex:$vaddr,
7501 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7502 }
7503
7504 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7505 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7506 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7507 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7508 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7509 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7510 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7511}
7512
7513// Only ld1/st1 has a v1d version.
7514multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7515 int Offset64, bits<4> opcode> {
7516 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7517 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7518 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7519 am_simdnoindex:$vaddr), []>;
7520 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7521 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7522 am_simdnoindex:$vaddr), []>;
7523 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7524 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7525 am_simdnoindex:$vaddr), []>;
7526 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7527 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7528 am_simdnoindex:$vaddr), []>;
7529 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7530 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7531 am_simdnoindex:$vaddr), []>;
7532 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7533 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7534 am_simdnoindex:$vaddr), []>;
7535 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7536 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7537 am_simdnoindex:$vaddr), []>;
7538
7539 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7540 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7541 am_simdnoindex:$vaddr,
7542 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7543 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7544 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7545 am_simdnoindex:$vaddr,
7546 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7547 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7548 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7549 am_simdnoindex:$vaddr,
7550 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7551 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7552 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7553 am_simdnoindex:$vaddr,
7554 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7555 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7556 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7557 am_simdnoindex:$vaddr,
7558 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7559 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7560 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7561 am_simdnoindex:$vaddr,
7562 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7563 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7564 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7565 am_simdnoindex:$vaddr,
7566 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7567 }
7568
7569 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7570 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7571 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7572 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7573 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7574 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7575 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7576}
7577
7578multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7579 int Offset128, int Offset64, bits<4> opcode>
7580 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7581
7582 // LD1 instructions have extra "1d" variants.
7583 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7584 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7585 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7586 (ins am_simdnoindex:$vaddr), []>;
7587
7588 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7589 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7590 (ins am_simdnoindex:$vaddr,
7591 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7592 }
7593
7594 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7595}
7596
7597multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7598 int Offset128, int Offset64, bits<4> opcode>
7599 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7600
7601 // ST1 instructions have extra "1d" variants.
7602 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7603 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7604 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7605 am_simdnoindex:$vaddr), []>;
7606
7607 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7608 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7609 am_simdnoindex:$vaddr,
7610 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7611 }
7612
7613 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7614}
7615
7616multiclass SIMDLd1Multiple<string asm> {
7617 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7618 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7619 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7620 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7621}
7622
7623multiclass SIMDSt1Multiple<string asm> {
7624 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7625 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7626 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7627 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7628}
7629
7630multiclass SIMDLd2Multiple<string asm> {
7631 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7632}
7633
7634multiclass SIMDSt2Multiple<string asm> {
7635 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7636}
7637
7638multiclass SIMDLd3Multiple<string asm> {
7639 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7640}
7641
7642multiclass SIMDSt3Multiple<string asm> {
7643 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7644}
7645
7646multiclass SIMDLd4Multiple<string asm> {
7647 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7648}
7649
7650multiclass SIMDSt4Multiple<string asm> {
7651 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7652}
7653
7654//---
7655// AdvSIMD Load/store single-element
7656//---
7657
7658class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7659 string asm, string operands, dag oops, dag iops,
7660 list<dag> pattern>
7661 : I<oops, iops, asm, operands, "", pattern> {
7662 bits<5> Vt;
7663 bits<5> vaddr;
7664 let Inst{31} = 0;
7665 let Inst{29-24} = 0b001101;
7666 let Inst{22} = L;
7667 let Inst{21} = R;
7668 let Inst{15-13} = opcode;
7669 let Inst{9-5} = vaddr;
7670 let Inst{4-0} = Vt;
7671 let DecoderMethod = "DecodeSIMDLdStSingle";
7672}
7673
7674class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7675 string asm, string operands, dag oops, dag iops,
7676 list<dag> pattern>
7677 : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7678 bits<5> Vt;
7679 bits<5> vaddr;
7680 let Inst{31} = 0;
7681 let Inst{29-24} = 0b001101;
7682 let Inst{22} = L;
7683 let Inst{21} = R;
7684 let Inst{15-13} = opcode;
7685 let Inst{9-5} = vaddr;
7686 let Inst{4-0} = Vt;
7687 let DecoderMethod = "DecodeSIMDLdStSingleTied";
7688}
7689
7690
7691let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7692class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7693 Operand listtype>
7694 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7695 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7696 let Inst{30} = Q;
7697 let Inst{23} = 0;
7698 let Inst{20-16} = 0b00000;
7699 let Inst{12} = S;
7700 let Inst{11-10} = size;
7701}
7702let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7703class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7704 string asm, Operand listtype, Operand GPR64pi>
7705 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7706 (outs listtype:$Vt),
7707 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7708 bits<5> Xm;
7709 let Inst{30} = Q;
7710 let Inst{23} = 1;
7711 let Inst{20-16} = Xm;
7712 let Inst{12} = S;
7713 let Inst{11-10} = size;
7714}
7715
7716multiclass SIMDLdrAliases<string asm, string layout, string Count,
7717 int Offset, int Size> {
7718 // E.g. "ld1r { v0.8b }, [x1], #1"
7719 // "ld1r.8b\t$Vt, $vaddr, #1"
7720 // may get mapped to
7721 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7722 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7723 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7724 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7725 am_simdnoindex:$vaddr, XZR), 1>;
7726
7727 // E.g. "ld1r.8b { v0 }, [x1], #1"
7728 // "ld1r.8b\t$Vt, $vaddr, #1"
7729 // may get mapped to
7730 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7731 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7732 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7733 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7734 am_simdnoindex:$vaddr, XZR), 0>;
7735
7736 // E.g. "ld1r.8b { v0 }, [x1]"
7737 // "ld1r.8b\t$Vt, $vaddr"
7738 // may get mapped to
7739 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7740 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7741 (!cast<Instruction>(NAME # "v" # layout)
7742 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7743 am_simdnoindex:$vaddr), 0>;
7744
7745 // E.g. "ld1r.8b { v0 }, [x1], x2"
7746 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7747 // may get mapped to
7748 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7749 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7750 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7751 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7752 am_simdnoindex:$vaddr,
7753 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7754}
7755
7756multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7757 int Offset1, int Offset2, int Offset4, int Offset8> {
7758 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7759 !cast<Operand>("VecList" # Count # "8b")>;
7760 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7761 !cast<Operand>("VecList" # Count #"16b")>;
7762 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7763 !cast<Operand>("VecList" # Count #"4h")>;
7764 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7765 !cast<Operand>("VecList" # Count #"8h")>;
7766 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7767 !cast<Operand>("VecList" # Count #"2s")>;
7768 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7769 !cast<Operand>("VecList" # Count #"4s")>;
7770 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7771 !cast<Operand>("VecList" # Count #"1d")>;
7772 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7773 !cast<Operand>("VecList" # Count #"2d")>;
7774
7775 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7776 !cast<Operand>("VecList" # Count # "8b"),
7777 !cast<Operand>("GPR64pi" # Offset1)>;
7778 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7779 !cast<Operand>("VecList" # Count # "16b"),
7780 !cast<Operand>("GPR64pi" # Offset1)>;
7781 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7782 !cast<Operand>("VecList" # Count # "4h"),
7783 !cast<Operand>("GPR64pi" # Offset2)>;
7784 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7785 !cast<Operand>("VecList" # Count # "8h"),
7786 !cast<Operand>("GPR64pi" # Offset2)>;
7787 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7788 !cast<Operand>("VecList" # Count # "2s"),
7789 !cast<Operand>("GPR64pi" # Offset4)>;
7790 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7791 !cast<Operand>("VecList" # Count # "4s"),
7792 !cast<Operand>("GPR64pi" # Offset4)>;
7793 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7794 !cast<Operand>("VecList" # Count # "1d"),
7795 !cast<Operand>("GPR64pi" # Offset8)>;
7796 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7797 !cast<Operand>("VecList" # Count # "2d"),
7798 !cast<Operand>("GPR64pi" # Offset8)>;
7799
7800 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7801 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7802 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7803 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7804 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7805 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7806 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7807 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7808}
7809
7810class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7811 dag oops, dag iops, list<dag> pattern>
7812 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7813 pattern> {
7814 // idx encoded in Q:S:size fields.
7815 bits<4> idx;
7816 let Inst{30} = idx{3};
7817 let Inst{23} = 0;
7818 let Inst{20-16} = 0b00000;
7819 let Inst{12} = idx{2};
7820 let Inst{11-10} = idx{1-0};
7821}
7822class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7823 dag oops, dag iops, list<dag> pattern>
7824 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7825 pattern> {
7826 // idx encoded in Q:S:size fields.
7827 bits<4> idx;
7828 let Inst{30} = idx{3};
7829 let Inst{23} = 0;
7830 let Inst{20-16} = 0b00000;
7831 let Inst{12} = idx{2};
7832 let Inst{11-10} = idx{1-0};
7833}
7834class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7835 dag oops, dag iops>
7836 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7837 oops, iops, []> {
7838 // idx encoded in Q:S:size fields.
7839 bits<4> idx;
7840 bits<5> Xm;
7841 let Inst{30} = idx{3};
7842 let Inst{23} = 1;
7843 let Inst{20-16} = Xm;
7844 let Inst{12} = idx{2};
7845 let Inst{11-10} = idx{1-0};
7846}
7847class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7848 dag oops, dag iops>
7849 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7850 oops, iops, []> {
7851 // idx encoded in Q:S:size fields.
7852 bits<4> idx;
7853 bits<5> Xm;
7854 let Inst{30} = idx{3};
7855 let Inst{23} = 1;
7856 let Inst{20-16} = Xm;
7857 let Inst{12} = idx{2};
7858 let Inst{11-10} = idx{1-0};
7859}
7860
7861class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7862 dag oops, dag iops, list<dag> pattern>
7863 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7864 pattern> {
7865 // idx encoded in Q:S:size<1> fields.
7866 bits<3> idx;
7867 let Inst{30} = idx{2};
7868 let Inst{23} = 0;
7869 let Inst{20-16} = 0b00000;
7870 let Inst{12} = idx{1};
7871 let Inst{11} = idx{0};
7872 let Inst{10} = size;
7873}
7874class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7875 dag oops, dag iops, list<dag> pattern>
7876 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7877 pattern> {
7878 // idx encoded in Q:S:size<1> fields.
7879 bits<3> idx;
7880 let Inst{30} = idx{2};
7881 let Inst{23} = 0;
7882 let Inst{20-16} = 0b00000;
7883 let Inst{12} = idx{1};
7884 let Inst{11} = idx{0};
7885 let Inst{10} = size;
7886}
7887
7888class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7889 dag oops, dag iops>
7890 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7891 oops, iops, []> {
7892 // idx encoded in Q:S:size<1> fields.
7893 bits<3> idx;
7894 bits<5> Xm;
7895 let Inst{30} = idx{2};
7896 let Inst{23} = 1;
7897 let Inst{20-16} = Xm;
7898 let Inst{12} = idx{1};
7899 let Inst{11} = idx{0};
7900 let Inst{10} = size;
7901}
7902class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7903 dag oops, dag iops>
7904 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7905 oops, iops, []> {
7906 // idx encoded in Q:S:size<1> fields.
7907 bits<3> idx;
7908 bits<5> Xm;
7909 let Inst{30} = idx{2};
7910 let Inst{23} = 1;
7911 let Inst{20-16} = Xm;
7912 let Inst{12} = idx{1};
7913 let Inst{11} = idx{0};
7914 let Inst{10} = size;
7915}
7916class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7917 dag oops, dag iops, list<dag> pattern>
7918 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7919 pattern> {
7920 // idx encoded in Q:S fields.
7921 bits<2> idx;
7922 let Inst{30} = idx{1};
7923 let Inst{23} = 0;
7924 let Inst{20-16} = 0b00000;
7925 let Inst{12} = idx{0};
7926 let Inst{11-10} = size;
7927}
7928class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7929 dag oops, dag iops, list<dag> pattern>
7930 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7931 pattern> {
7932 // idx encoded in Q:S fields.
7933 bits<2> idx;
7934 let Inst{30} = idx{1};
7935 let Inst{23} = 0;
7936 let Inst{20-16} = 0b00000;
7937 let Inst{12} = idx{0};
7938 let Inst{11-10} = size;
7939}
7940class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7941 string asm, dag oops, dag iops>
7942 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7943 oops, iops, []> {
7944 // idx encoded in Q:S fields.
7945 bits<2> idx;
7946 bits<5> Xm;
7947 let Inst{30} = idx{1};
7948 let Inst{23} = 1;
7949 let Inst{20-16} = Xm;
7950 let Inst{12} = idx{0};
7951 let Inst{11-10} = size;
7952}
7953class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7954 string asm, dag oops, dag iops>
7955 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7956 oops, iops, []> {
7957 // idx encoded in Q:S fields.
7958 bits<2> idx;
7959 bits<5> Xm;
7960 let Inst{30} = idx{1};
7961 let Inst{23} = 1;
7962 let Inst{20-16} = Xm;
7963 let Inst{12} = idx{0};
7964 let Inst{11-10} = size;
7965}
7966class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7967 dag oops, dag iops, list<dag> pattern>
7968 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7969 pattern> {
7970 // idx encoded in Q field.
7971 bits<1> idx;
7972 let Inst{30} = idx;
7973 let Inst{23} = 0;
7974 let Inst{20-16} = 0b00000;
7975 let Inst{12} = 0;
7976 let Inst{11-10} = size;
7977}
7978class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7979 dag oops, dag iops, list<dag> pattern>
7980 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7981 pattern> {
7982 // idx encoded in Q field.
7983 bits<1> idx;
7984 let Inst{30} = idx;
7985 let Inst{23} = 0;
7986 let Inst{20-16} = 0b00000;
7987 let Inst{12} = 0;
7988 let Inst{11-10} = size;
7989}
7990class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7991 string asm, dag oops, dag iops>
7992 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7993 oops, iops, []> {
7994 // idx encoded in Q field.
7995 bits<1> idx;
7996 bits<5> Xm;
7997 let Inst{30} = idx;
7998 let Inst{23} = 1;
7999 let Inst{20-16} = Xm;
8000 let Inst{12} = 0;
8001 let Inst{11-10} = size;
8002}
8003class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8004 string asm, dag oops, dag iops>
8005 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8006 oops, iops, []> {
8007 // idx encoded in Q field.
8008 bits<1> idx;
8009 bits<5> Xm;
8010 let Inst{30} = idx;
8011 let Inst{23} = 1;
8012 let Inst{20-16} = Xm;
8013 let Inst{12} = 0;
8014 let Inst{11-10} = size;
8015}
8016
8017let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8018multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8019 RegisterOperand listtype,
8020 RegisterOperand GPR64pi> {
8021 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8022 (outs listtype:$dst),
8023 (ins listtype:$Vt, VectorIndexB:$idx,
8024 am_simdnoindex:$vaddr), []>;
8025
8026 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8027 (outs listtype:$dst),
8028 (ins listtype:$Vt, VectorIndexB:$idx,
8029 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8030}
8031let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8032multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8033 RegisterOperand listtype,
8034 RegisterOperand GPR64pi> {
8035 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8036 (outs listtype:$dst),
8037 (ins listtype:$Vt, VectorIndexH:$idx,
8038 am_simdnoindex:$vaddr), []>;
8039
8040 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8041 (outs listtype:$dst),
8042 (ins listtype:$Vt, VectorIndexH:$idx,
8043 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8044}
8045let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8046multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8047 RegisterOperand listtype,
8048 RegisterOperand GPR64pi> {
8049 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8050 (outs listtype:$dst),
8051 (ins listtype:$Vt, VectorIndexS:$idx,
8052 am_simdnoindex:$vaddr), []>;
8053
8054 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8055 (outs listtype:$dst),
8056 (ins listtype:$Vt, VectorIndexS:$idx,
8057 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8058}
8059let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8060multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008061 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008062 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8063 (outs listtype:$dst),
8064 (ins listtype:$Vt, VectorIndexD:$idx,
8065 am_simdnoindex:$vaddr), []>;
8066
8067 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8068 (outs listtype:$dst),
8069 (ins listtype:$Vt, VectorIndexD:$idx,
8070 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8071}
8072let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8073multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008074 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008075 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8076 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008077 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008078
8079 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8080 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8081 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8082}
8083let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8084multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008085 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008086 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8087 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008088 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008089
8090 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8091 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8092 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8093}
8094let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8095multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008096 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008097 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8098 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008099 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008100
8101 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8102 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8103 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8104}
8105let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8106multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008107 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008108 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8109 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008110 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008111
8112 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8113 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8114 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8115}
8116
8117multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8118 string Count, int Offset, Operand idxtype> {
8119 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8120 // "ld1\t$Vt, $vaddr, #1"
8121 // may get mapped to
8122 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8123 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8124 (!cast<Instruction>(NAME # Type # "_POST")
8125 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8126 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8127
8128 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8129 // "ld1.8b\t$Vt, $vaddr, #1"
8130 // may get mapped to
8131 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8132 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8133 (!cast<Instruction>(NAME # Type # "_POST")
8134 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8135 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8136
8137 // E.g. "ld1.8b { v0 }[0], [x1]"
8138 // "ld1.8b\t$Vt, $vaddr"
8139 // may get mapped to
8140 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8141 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8142 (!cast<Instruction>(NAME # Type)
8143 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8144 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8145
8146 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8147 // "ld1.8b\t$Vt, $vaddr, $Xm"
8148 // may get mapped to
8149 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8150 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8151 (!cast<Instruction>(NAME # Type # "_POST")
8152 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8153 idxtype:$idx, am_simdnoindex:$vaddr,
8154 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8155}
8156
8157multiclass SIMDLdSt1SingleAliases<string asm> {
8158 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8159 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8160 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8161 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8162}
8163
8164multiclass SIMDLdSt2SingleAliases<string asm> {
8165 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8166 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8167 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8168 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8169}
8170
8171multiclass SIMDLdSt3SingleAliases<string asm> {
8172 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8173 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8174 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8175 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8176}
8177
8178multiclass SIMDLdSt4SingleAliases<string asm> {
8179 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8180 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8181 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8182 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8183}
8184
8185//----------------------------------------------------------------------------
8186// Crypto extensions
8187//----------------------------------------------------------------------------
8188
8189let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8190class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8191 list<dag> pat>
8192 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8193 Sched<[WriteV]>{
8194 bits<5> Rd;
8195 bits<5> Rn;
8196 let Inst{31-16} = 0b0100111000101000;
8197 let Inst{15-12} = opc;
8198 let Inst{11-10} = 0b10;
8199 let Inst{9-5} = Rn;
8200 let Inst{4-0} = Rd;
8201}
8202
8203class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8204 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8205 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8206
8207class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8208 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8209 "$Rd = $dst",
8210 [(set (v16i8 V128:$dst),
8211 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8212
8213let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8214class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8215 dag oops, dag iops, list<dag> pat>
8216 : I<oops, iops, asm,
8217 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8218 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8219 Sched<[WriteV]>{
8220 bits<5> Rd;
8221 bits<5> Rn;
8222 bits<5> Rm;
8223 let Inst{31-21} = 0b01011110000;
8224 let Inst{20-16} = Rm;
8225 let Inst{15} = 0;
8226 let Inst{14-12} = opc;
8227 let Inst{11-10} = 0b00;
8228 let Inst{9-5} = Rn;
8229 let Inst{4-0} = Rd;
8230}
8231
8232class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8233 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8234 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8235 [(set (v4i32 FPR128:$dst),
8236 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8237 (v4i32 V128:$Rm)))]>;
8238
8239class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8240 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8241 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8242 [(set (v4i32 V128:$dst),
8243 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8244 (v4i32 V128:$Rm)))]>;
8245
8246class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8247 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8248 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8249 [(set (v4i32 FPR128:$dst),
8250 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8251 (v4i32 V128:$Rm)))]>;
8252
8253let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8254class SHA2OpInst<bits<4> opc, string asm, string kind,
8255 string cstr, dag oops, dag iops,
8256 list<dag> pat>
8257 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8258 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8259 Sched<[WriteV]>{
8260 bits<5> Rd;
8261 bits<5> Rn;
8262 let Inst{31-16} = 0b0101111000101000;
8263 let Inst{15-12} = opc;
8264 let Inst{11-10} = 0b10;
8265 let Inst{9-5} = Rn;
8266 let Inst{4-0} = Rd;
8267}
8268
8269class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8270 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8271 (ins V128:$Rd, V128:$Rn),
8272 [(set (v4i32 V128:$dst),
8273 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8274
8275class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8276 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8277 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8278
8279// Allow the size specifier tokens to be upper case, not just lower.
8280def : TokenAlias<".8B", ".8b">;
8281def : TokenAlias<".4H", ".4h">;
8282def : TokenAlias<".2S", ".2s">;
8283def : TokenAlias<".1D", ".1d">;
8284def : TokenAlias<".16B", ".16b">;
8285def : TokenAlias<".8H", ".8h">;
8286def : TokenAlias<".4S", ".4s">;
8287def : TokenAlias<".2D", ".2d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008288def : TokenAlias<".1Q", ".1q">;
Tim Northover00ed9962014-03-29 10:18:08 +00008289def : TokenAlias<".B", ".b">;
8290def : TokenAlias<".H", ".h">;
8291def : TokenAlias<".S", ".s">;
8292def : TokenAlias<".D", ".d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008293def : TokenAlias<".Q", ".q">;