llvm.org GIT mirror llvm / 9e08876
Added sub-formats to the NeonI/NeonXI instructions to further refine the NEONFrm instructions to help disassembly. We also changed the output of the addressing modes to omit the '+' from the assembler syntax #+/-<imm> or +/-<Rm>. See, for example, A8.6.57/58/60. And modified test cases to not expect '+' in +reg or #+num. For example, ; CHECK: ldr.w r9, [r7, #28] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98745 91177308-0d34-0410-b5e6-96231b3b80d8 Johnny Chen 9 years ago
20 changed file(s) with 955 addition(s) and 166 deletion(s). Raw diff Collapse all Expand all
3434 add = '+', sub = '-'
3535 };
3636
37 static inline const char *getAddrOpcStr(AddrOpc Op) {
38 return Op == sub ? "-" : "";
39 }
40
3741 static inline const char *getShiftOpcStr(ShiftOpc Op) {
3842 switch (Op) {
3943 default: assert(0 && "Unknown shift opc!");
126130 return (Imm >> 8) * 2;
127131 }
128132
133 /// getSOImmValOneRotate - Try to handle Imm with an immediate shifter
134 /// operand, computing the rotate amount to use. If this immediate value
135 /// cannot be handled with a single shifter-op, return 0.
136 static inline unsigned getSOImmValOneRotate(unsigned Imm) {
137 // A5.2.4 Constants with multiple encodings
138 // The lowest unsigned value of rotation wins!
139 for (unsigned R = 1; R <= 15; ++R)
140 if ((Imm & rotr32(~255U, 2*R)) == 0)
141 return 2*R;
142
143 // Failed to find a suitable rotate amount.
144 return 0;
145 }
146
129147 /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
130148 /// computing the rotate amount to use. If this immediate value cannot be
131149 /// handled with a single shifter-op, determine a good rotate amount that will
178196 // of zero.
179197 if ((Arg & ~255U) == 0) return Arg;
180198
181 unsigned RotAmt = getSOImmValRotate(Arg);
199 unsigned RotAmt = getSOImmValOneRotate(Arg);
182200
183201 // If this cannot be handled with a single shifter_op, bail out.
184202 if (rotr32(~255U, RotAmt) & Arg)
14631463 // ARM NEON Instruction templates.
14641464 //
14651465
1466 // NSFormat specifies further details of a NEON instruction. This is used by
1467 // the disassembler to classify NEONFrm instructions for disassembly purpose.
1468 class NSFormat val> {
1469 bits<5> Value = val;
1470 }
1471 def NSFormatNone : NSFormat<0>;
1472 def VLDSTLaneFrm : NSFormat<1>;
1473 def VLDSTLaneDblFrm : NSFormat<2>;
1474 def VLDSTRQFrm : NSFormat<3>;
1475 def NVdImmFrm : NSFormat<4>;
1476 def NVdVmImmFrm : NSFormat<5>;
1477 def NVdVmImmVCVTFrm : NSFormat<6>;
1478 def NVdVmImmVDupLaneFrm : NSFormat<7>;
1479 def NVdVmImmVSHLLFrm : NSFormat<8>;
1480 def NVectorShuffleFrm : NSFormat<9>;
1481 def NVectorShiftFrm : NSFormat<10>;
1482 def NVectorShift2Frm : NSFormat<11>;
1483 def NVdVnVmImmFrm : NSFormat<12>;
1484 def NVdVnVmImmVectorShiftFrm : NSFormat<13>;
1485 def NVdVnVmImmVectorExtractFrm : NSFormat<14>;
1486 def NVdVnVmImmMulScalarFrm : NSFormat<15>;
1487 def VTBLFrm : NSFormat<16>;
1488
14661489 class NeonI
14671490 string opc, string dt, string asm, string cstr, list pattern>
14681491 : InstARM {
14731496 !strconcat("\t", asm));
14741497 let Pattern = pattern;
14751498 list Predicates = [HasNEON];
1499 NSFormat NSF = NSFormatNone; // For disassembly.
1500 bits<5> NSForm = NSFormatNone.Value; // For disassembly.
14761501 }
14771502
14781503 // Same as NeonI except it does not have a "data type" specifier.
14841509 let AsmString = !strconcat(!strconcat(opc, "${p}"), !strconcat("\t", asm));
14851510 let Pattern = pattern;
14861511 list Predicates = [HasNEON];
1512 NSFormat NSF = NSFormatNone; // For disassembly.
1513 bits<5> NSForm = NSFormatNone.Value; // For disassembly.
14871514 }
14881515
14891516 class NI
14961523 string asm, list pattern>
14971524 : NeonXI
14981525 pattern> {
1526 let NSF = VLDSTRQFrm; // For disassembly.
1527 let NSForm = VLDSTRQFrm.Value; // For disassembly.
14991528 }
15001529
15011530 class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4,
15081537 let Inst{21-20} = op21_20;
15091538 let Inst{11-8} = op11_8;
15101539 let Inst{7-4} = op7_4;
1540 let NSF = VLDSTLaneFrm; // For disassembly.
1541 let NSForm = VLDSTLaneFrm.Value; // For disassembly.
15111542 }
15121543
15131544 class NDataI
15371568 let Inst{6} = op6;
15381569 let Inst{5} = op5;
15391570 let Inst{4} = op4;
1571 let NSF = NVdImmFrm; // For disassembly.
1572 let NSForm = NVdImmFrm.Value; // For disassembly.
15401573 }
15411574
15421575 // NEON 2 vector register format.
15521585 let Inst{11-7} = op11_7;
15531586 let Inst{6} = op6;
15541587 let Inst{4} = op4;
1588 let NSF = NVdVmImmFrm; // For disassembly.
1589 let NSForm = NVdVmImmFrm.Value; // For disassembly.
15551590 }
15561591
15571592 // Same as N2V except it doesn't have a datatype suffix.
15671602 let Inst{11-7} = op11_7;
15681603 let Inst{6} = op6;
15691604 let Inst{4} = op4;
1605 let NSF = NVdVmImmFrm; // For disassembly.
1606 let NSForm = NVdVmImmFrm.Value; // For disassembly.
15701607 }
15711608
15721609 // NEON 2 vector register with immediate.
15801617 let Inst{7} = op7;
15811618 let Inst{6} = op6;
15821619 let Inst{4} = op4;
1620 let NSF = NVdVmImmFrm; // For disassembly.
1621 let NSForm = NVdVmImmFrm.Value; // For disassembly.
15831622 }
15841623
15851624 // NEON 3 vector register format.
15931632 let Inst{11-8} = op11_8;
15941633 let Inst{6} = op6;
15951634 let Inst{4} = op4;
1635 let NSF = NVdVnVmImmFrm; // For disassembly.
1636 let NSForm = NVdVnVmImmFrm.Value; // For disassembly.
15961637 }
15971638
15981639 // Same as N3VX except it doesn't have a data type suffix.
16061647 let Inst{11-8} = op11_8;
16071648 let Inst{6} = op6;
16081649 let Inst{4} = op4;
1650 let NSF = NVdVnVmImmFrm; // For disassembly.
1651 let NSForm = NVdVnVmImmFrm.Value; // For disassembly.
16091652 }
16101653
16111654 // NEON VMOVs between scalar and core registers.
212212 class VLD2Ddbl op7_4, string OpcodeStr, string Dt>
213213 : NLdSt<0,0b10,0b1001,op7_4, (outs DPR:$dst1, DPR:$dst2),
214214 (ins addrmode6:$addr), IIC_VLD2,
215 OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []>;
215 OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []> {
216 let NSF = VLDSTLaneDblFrm; // For disassembly.
217 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
218 }
216219
217220 def VLD2d8D : VLD2Ddbl<0b0000, "vld2", "8">;
218221 def VLD2d16D : VLD2Ddbl<0b0100, "vld2", "16">;
227230 : NLdSt<0,0b10,0b0101,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, GPR:$wb),
228231 (ins addrmode6:$addr), IIC_VLD3,
229232 OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3\\}, $addr",
230 "$addr.addr = $wb", []>;
233 "$addr.addr = $wb", []> {
234 let NSF = VLDSTLaneDblFrm; // For disassembly.
235 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
236 }
231237
232238 def VLD3d8 : VLD3D<0b0000, "vld3", "8">;
233239 def VLD3d16 : VLD3D<0b0100, "vld3", "16">;
259265 (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb),
260266 (ins addrmode6:$addr), IIC_VLD4,
261267 OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr",
262 "$addr.addr = $wb", []>;
268 "$addr.addr = $wb", []> {
269 let NSF = VLDSTLaneDblFrm; // For disassembly.
270 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
271 }
263272
264273 def VLD4d8 : VLD4D<0b0000, "vld4", "8">;
265274 def VLD4d16 : VLD4D<0b0100, "vld4", "16">;
296305 def VLD2LNd32 : VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 0; }
297306
298307 // vld2 to double-spaced even registers.
299 def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 1; }
300 def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 1; }
308 def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> {
309 let Inst{5} = 1;
310 let NSF = VLDSTLaneDblFrm; // For disassembly.
311 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
312 }
313 def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> {
314 let Inst{6} = 1;
315 let NSF = VLDSTLaneDblFrm; // For disassembly.
316 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
317 }
301318
302319 // vld2 to double-spaced odd registers.
303 def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 1; }
304 def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 1; }
320 def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> {
321 let Inst{5} = 1;
322 let NSF = VLDSTLaneDblFrm; // For disassembly.
323 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
324 }
325 def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> {
326 let Inst{6} = 1;
327 let NSF = VLDSTLaneDblFrm; // For disassembly.
328 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
329 }
305330
306331 // VLD3LN : Vector Load (single 3-element structure to one lane)
307332 class VLD3LN op11_8, string OpcodeStr, string Dt>
317342 def VLD3LNd32 : VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b000; }
318343
319344 // vld3 to double-spaced even registers.
320 def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> { let Inst{5-4} = 0b10; }
345 def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> {
346 let Inst{5-4} = 0b10;
347 let NSF = VLDSTLaneDblFrm; // For disassembly.
348 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
349 }
321350 def VLD3LNq32a: VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b100; }
322351
323352 // vld3 to double-spaced odd registers.
339368 def VLD4LNd32 : VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 0; }
340369
341370 // vld4 to double-spaced even registers.
342 def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 1; }
343 def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 1; }
371 def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> {
372 let Inst{5} = 1;
373 let NSF = VLDSTLaneDblFrm; // For disassembly.
374 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
375 }
376 def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> {
377 let Inst{6} = 1;
378 let NSF = VLDSTLaneDblFrm; // For disassembly.
379 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
380 }
344381
345382 // vld4 to double-spaced odd registers.
346 def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 1; }
347 def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 1; }
383 def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> {
384 let Inst{5} = 1;
385 let NSF = VLDSTLaneDblFrm; // For disassembly.
386 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
387 }
388 def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> {
389 let Inst{6} = 1;
390 let NSF = VLDSTLaneDblFrm; // For disassembly.
391 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
392 }
348393
349394 // VLD1DUP : Vector Load (single element to all lanes)
350395 // VLD2DUP : Vector Load (single 2-element structure to all lanes)
432477 class VST2Ddbl op7_4, string OpcodeStr, string Dt>
433478 : NLdSt<0, 0b00, 0b1001, op7_4, (outs),
434479 (ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST,
435 OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []>;
480 OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []> {
481 let NSF = VLDSTLaneDblFrm; // For disassembly.
482 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
483 }
436484
437485 def VST2d8D : VST2Ddbl<0b0000, "vst2", "8">;
438486 def VST2d16D : VST2Ddbl<0b0100, "vst2", "16">;
447495 : NLdSt<0,0b00,0b0101,op7_4, (outs GPR:$wb),
448496 (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST,
449497 OpcodeStr, Dt, "\\{$src1, $src2, $src3\\}, $addr",
450 "$addr.addr = $wb", []>;
498 "$addr.addr = $wb", []> {
499 let NSF = VLDSTLaneDblFrm; // For disassembly.
500 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
501 }
451502
452503 def VST3d8 : VST3D<0b0000, "vst3", "8">;
453504 def VST3d16 : VST3D<0b0100, "vst3", "16">;
477528 : NLdSt<0,0b00,0b0001,op7_4, (outs GPR:$wb),
478529 (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4),
479530 IIC_VST, OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr",
480 "$addr.addr = $wb", []>;
531 "$addr.addr = $wb", []> {
532 let NSF = VLDSTLaneDblFrm; // For disassembly.
533 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
534 }
481535
482536 def VST4d8 : VST4D<0b0000, "vst4", "8">;
483537 def VST4d16 : VST4D<0b0100, "vst4", "16">;
514568 def VST2LNd32 : VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 0; }
515569
516570 // vst2 to double-spaced even registers.
517 def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 1; }
518 def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 1; }
571 def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> {
572 let Inst{5} = 1;
573 let NSF = VLDSTLaneDblFrm; // For disassembly.
574 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
575 }
576 def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> {
577 let Inst{6} = 1;
578 let NSF = VLDSTLaneDblFrm; // For disassembly.
579 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
580 }
519581
520582 // vst2 to double-spaced odd registers.
521 def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 1; }
522 def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 1; }
583 def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> {
584 let Inst{5} = 1;
585 let NSF = VLDSTLaneDblFrm; // For disassembly.
586 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
587 }
588 def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> {
589 let Inst{6} = 1;
590 let NSF = VLDSTLaneDblFrm; // For disassembly.
591 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
592 }
523593
524594 // VST3LN : Vector Store (single 3-element structure from one lane)
525595 class VST3LN op11_8, string OpcodeStr, string Dt>
534604 def VST3LNd32 : VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b000; }
535605
536606 // vst3 to double-spaced even registers.
537 def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b10; }
538 def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b100; }
607 def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> {
608 let Inst{5-4} = 0b10;
609 let NSF = VLDSTLaneDblFrm; // For disassembly.
610 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
611 }
612 def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> {
613 let Inst{6-4} = 0b100;
614 let NSF = VLDSTLaneDblFrm; // For disassembly.
615 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
616 }
539617
540618 // vst3 to double-spaced odd registers.
541 def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b10; }
542 def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b100; }
619 def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> {
620 let Inst{5-4} = 0b10;
621 let NSF = VLDSTLaneDblFrm; // For disassembly.
622 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
623 }
624 def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> {
625 let Inst{6-4} = 0b100;
626 let NSF = VLDSTLaneDblFrm; // For disassembly.
627 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
628 }
543629
544630 // VST4LN : Vector Store (single 4-element structure from one lane)
545631 class VST4LN op11_8, string OpcodeStr, string Dt>
555641 def VST4LNd32 : VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 0; }
556642
557643 // vst4 to double-spaced even registers.
558 def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 1; }
559 def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 1; }
644 def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> {
645 let Inst{5} = 1;
646 let NSF = VLDSTLaneDblFrm; // For disassembly.
647 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
648 }
649 def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> {
650 let Inst{6} = 1;
651 let NSF = VLDSTLaneDblFrm; // For disassembly.
652 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
653 }
560654
561655 // vst4 to double-spaced odd registers.
562 def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 1; }
563 def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 1; }
656 def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> {
657 let Inst{5} = 1;
658 let NSF = VLDSTLaneDblFrm; // For disassembly.
659 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
660 }
661 def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> {
662 let Inst{6} = 1;
663 let NSF = VLDSTLaneDblFrm; // For disassembly.
664 let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
665 }
564666
565667 } // mayStore = 1, hasExtraSrcRegAllocReq = 1
566668
667769 : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 0, 0, (outs DPR:$dst1, DPR:$dst2),
668770 (ins DPR:$src1, DPR:$src2), IIC_VPERMD,
669771 OpcodeStr, Dt, "$dst1, $dst2",
670 "$src1 = $dst1, $src2 = $dst2", []>;
772 "$src1 = $dst1, $src2 = $dst2", []> {
773 let NSF = NVectorShuffleFrm; // For disassembly.
774 let NSForm = NVectorShuffleFrm.Value; // For disassembly.
775 }
671776 class N2VQShuffle op19_18, bits<5> op11_7,
672777 InstrItinClass itin, string OpcodeStr, string Dt>
673778 : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 1, 0, (outs QPR:$dst1, QPR:$dst2),
674779 (ins QPR:$src1, QPR:$src2), itin, OpcodeStr, Dt, "$dst1, $dst2",
675 "$src1 = $dst1, $src2 = $dst2", []>;
780 "$src1 = $dst1, $src2 = $dst2", []> {
781 let NSF = NVectorShuffleFrm; // For disassembly.
782 let NSForm = NVectorShuffleFrm.Value; // For disassembly.
783 }
676784
677785 // Basic 3-register operations: single-, double- and quad-register.
678786 class N3VS op21_20, bits<4> op11_8, bit op4,
714822 (Ty (ShOp (Ty DPR:$src1),
715823 (Ty (NEONvduplane (Ty DPR_VFP2:$src2), imm:$lane)))))]>{
716824 let isCommutable = 0;
825 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
826 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
717827 }
718828 class N3VDSL16 op21_20, bits<4> op11_8,
719829 string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp>
724834 (Ty (ShOp (Ty DPR:$src1),
725835 (Ty (NEONvduplane (Ty DPR_8:$src2), imm:$lane)))))]> {
726836 let isCommutable = 0;
837 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
838 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
727839 }
728840
729841 class N3VQ op21_20, bits<4> op11_8, bit op4,
755867 (ResTy (NEONvduplane (OpTy DPR_VFP2:$src2),
756868 imm:$lane)))))]> {
757869 let isCommutable = 0;
870 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
871 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
758872 }
759873 class N3VQSL16 op21_20, bits<4> op11_8, string OpcodeStr, string Dt,
760874 ValueType ResTy, ValueType OpTy, SDNode ShOp>
766880 (ResTy (NEONvduplane (OpTy DPR_8:$src2),
767881 imm:$lane)))))]> {
768882 let isCommutable = 0;
883 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
884 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
769885 }
770886
771887 // Basic 3-register intrinsics, both double- and quad-register.
788904 (Ty (NEONvduplane (Ty DPR_VFP2:$src2),
789905 imm:$lane)))))]> {
790906 let isCommutable = 0;
907 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
908 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
791909 }
792910 class N3VDIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin,
793911 string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp>
799917 (Ty (NEONvduplane (Ty DPR_8:$src2),
800918 imm:$lane)))))]> {
801919 let isCommutable = 0;
920 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
921 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
802922 }
803923
804924 class N3VQInt op21_20, bits<4> op11_8, bit op4,
821941 (ResTy (NEONvduplane (OpTy DPR_VFP2:$src2),
822942 imm:$lane)))))]> {
823943 let isCommutable = 0;
944 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
945 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
824946 }
825947 class N3VQIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin,
826948 string OpcodeStr, string Dt,
833955 (ResTy (NEONvduplane (OpTy DPR_8:$src2),
834956 imm:$lane)))))]> {
835957 let isCommutable = 0;
958 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
959 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
836960 }
837961
838962 // Multiply-Add/Sub operations: single-, double- and quad-register.
863987 (Ty (ShOp (Ty DPR:$src1),
864988 (Ty (MulOp DPR:$src2,
865989 (Ty (NEONvduplane (Ty DPR_VFP2:$src3),
866 imm:$lane)))))))]>;
990 imm:$lane)))))))]> {
991 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
992 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
993 }
867994 class N3VDMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin,
868995 string OpcodeStr, string Dt,
869996 ValueType Ty, SDNode MulOp, SDNode ShOp>
8751002 (Ty (ShOp (Ty DPR:$src1),
8761003 (Ty (MulOp DPR:$src2,
8771004 (Ty (NEONvduplane (Ty DPR_8:$src3),
878 imm:$lane)))))))]>;
1005 imm:$lane)))))))]> {
1006 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
1007 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
1008 }
8791009
8801010 class N3VQMulOp op21_20, bits<4> op11_8, bit op4,
8811011 InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty,
8961026 (ResTy (ShOp (ResTy QPR:$src1),
8971027 (ResTy (MulOp QPR:$src2,
8981028 (ResTy (NEONvduplane (OpTy DPR_VFP2:$src3),
899 imm:$lane)))))))]>;
1029 imm:$lane)))))))]> {
1030 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
1031 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
1032 }
9001033 class N3VQMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin,
9011034 string OpcodeStr, string Dt,
9021035 ValueType ResTy, ValueType OpTy,
9091042 (ResTy (ShOp (ResTy QPR:$src1),
9101043 (ResTy (MulOp QPR:$src2,
9111044 (ResTy (NEONvduplane (OpTy DPR_8:$src3),
912 imm:$lane)))))))]>;
1045 imm:$lane)))))))]> {
1046 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
1047 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
1048 }
9131049
9141050 // Neon 3-argument intrinsics, both double- and quad-register.
9151051 // The destination register is also used as the first source operand register.
9951131 [(set (ResTy QPR:$dst),
9961132 (ResTy (IntOp (OpTy DPR:$src1),
9971133 (OpTy (NEONvduplane (OpTy DPR_VFP2:$src2),
998 imm:$lane)))))]>;
1134 imm:$lane)))))]> {
1135 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
1136 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
1137 }
9991138 class N3VLIntSL16 op21_20, bits<4> op11_8,
10001139 InstrItinClass itin, string OpcodeStr, string Dt,
10011140 ValueType ResTy, ValueType OpTy, Intrinsic IntOp>
10051144 [(set (ResTy QPR:$dst),
10061145 (ResTy (IntOp (OpTy DPR:$src1),
10071146 (OpTy (NEONvduplane (OpTy DPR_8:$src2),
1008 imm:$lane)))))]>;
1147 imm:$lane)))))]> {
1148 let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
1149 let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
1150 }
10091151
10101152 // Wide 3-register intrinsics.
10111153 class N3VWInt op21_20, bits<4> op11_8, bit op4,
10541196 OpcodeStr, Dt, "$dst, $src2", "$src1 = $dst",
10551197 [(set QPR:$dst, (ResTy (IntOp (ResTy QPR:$src1), (OpTy QPR:$src2))))]>;
10561198
1199 // This is a big let * in block to mark these instructions NVectorShiftFrm to
1200 // help the disassembler.
1201 let NSF = NVectorShiftFrm, NSForm = NVectorShiftFrm.Value in {
1202
10571203 // Shift by immediate,
10581204 // both double- and quad-register.
10591205 class N2VDSh op11_8, bit op7, bit op4,
10711217 OpcodeStr, Dt, "$dst, $src, $SIMM", "",
10721218 [(set QPR:$dst, (Ty (OpNode (Ty QPR:$src), (i32 imm:$SIMM))))]>;
10731219
1074 // Long shift by immediate.
1075 class N2VLSh op11_8, bit op7, bit op6, bit op4,
1076 string OpcodeStr, string Dt,
1077 ValueType ResTy, ValueType OpTy, SDNode OpNode>
1078 : N2VImm
1079 (outs QPR:$dst), (ins DPR:$src, i32imm:$SIMM), IIC_VSHLiD,
1080 OpcodeStr, Dt, "$dst, $src, $SIMM", "",
1081 [(set QPR:$dst, (ResTy (OpNode (OpTy DPR:$src),
1082 (i32 imm:$SIMM))))]>;
1083
10841220 // Narrow shift by immediate.
10851221 class N2VNSh op11_8, bit op7, bit op6, bit op4,
10861222 InstrItinClass itin, string OpcodeStr, string Dt,
11231259 OpcodeStr, Dt, "$dst, $src2, $SIMM", "$src1 = $dst",
11241260 [(set QPR:$dst, (Ty (ShOp QPR:$src1, QPR:$src2, (i32 imm:$SIMM))))]>;
11251261
1262 } // End of "let NSF = NVectorShiftFrm, ..."
1263
1264 // Long shift by immediate.
1265 class N2VLSh op11_8, bit op7, bit op6, bit op4,
1266 string OpcodeStr, string Dt,
1267 ValueType ResTy, ValueType OpTy, SDNode OpNode>
1268 : N2VImm
1269 (outs QPR:$dst), (ins DPR:$src, i32imm:$SIMM), IIC_VSHLiD,
1270 OpcodeStr, Dt, "$dst, $src, $SIMM", "",
1271 [(set QPR:$dst, (ResTy (OpNode (OpTy DPR:$src),
1272 (i32 imm:$SIMM))))]> {
1273 // This has a different interpretation of the shift amount encoding than
1274 // NVectorShiftFrm.
1275 let NSF = NVectorShift2Frm; // For disassembly.
1276 let NSForm = NVectorShift2Frm.Value; // For disassembly.
1277 }
1278
11261279 // Convert, with fractional bits immediate,
11271280 // both double- and quad-register.
1281 let NSF = NVdVmImmVCVTFrm, NSForm = NVdVmImmVCVTFrm.Value in {
11281282 class N2VCvtD op11_8, bit op7, bit op4,
11291283 string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy,
11301284 Intrinsic IntOp>
11391293 (outs QPR:$dst), (ins QPR:$src, i32imm:$SIMM), IIC_VUNAQ,
11401294 OpcodeStr, Dt, "$dst, $src, $SIMM", "",
11411295 [(set QPR:$dst, (ResTy (IntOp (OpTy QPR:$src), (i32 imm:$SIMM))))]>;
1296 }
11421297
11431298 //===----------------------------------------------------------------------===//
11441299 // Multiclasses
13491504 v2i64, v2i64, IntOp, Commutable>;
13501505 }
13511506
1507 // Same as N3VInt_QHSD, except they're for Vector Shift (Register) Instructions.
1508 // D:Vd M:Vm N:Vn (notice that M:Vm is the first operand)
1509 // This helps the disassembler.
1510 let NSF = NVdVnVmImmVectorShiftFrm, NSForm = NVdVnVmImmVectorShiftFrm.Value in {
1511 multiclass N3VInt_HS2 op11_8, bit op4,
1512 InstrItinClass itinD16, InstrItinClass itinD32,
1513 InstrItinClass itinQ16, InstrItinClass itinQ32,
1514 string OpcodeStr, string Dt,
1515 Intrinsic IntOp, bit Commutable = 0> {
1516 // 64-bit vector types.
1517 def v4i16 : N3VDInt
1518 OpcodeStr, !strconcat(Dt, "16"),
1519 v4i16, v4i16, IntOp, Commutable>;
1520 def v2i32 : N3VDInt
1521 OpcodeStr, !strconcat(Dt, "32"),
1522 v2i32, v2i32, IntOp, Commutable>;
1523
1524 // 128-bit vector types.
1525 def v8i16 : N3VQInt
1526 OpcodeStr, !strconcat(Dt, "16"),
1527 v8i16, v8i16, IntOp, Commutable>;
1528 def v4i32 : N3VQInt
1529 OpcodeStr, !strconcat(Dt, "32"),
1530 v4i32, v4i32, IntOp, Commutable>;
1531 }
1532 multiclass N3VInt_QHS2 op11_8, bit op4,
1533 InstrItinClass itinD16, InstrItinClass itinD32,
1534 InstrItinClass itinQ16, InstrItinClass itinQ32,
1535 string OpcodeStr, string Dt,
1536 Intrinsic IntOp, bit Commutable = 0>
1537 : N3VInt_HS2
1538 OpcodeStr, Dt, IntOp, Commutable> {
1539 def v8i8 : N3VDInt
1540 OpcodeStr, !strconcat(Dt, "8"),
1541 v8i8, v8i8, IntOp, Commutable>;
1542 def v16i8 : N3VQInt
1543 OpcodeStr, !strconcat(Dt, "8"),
1544 v16i8, v16i8, IntOp, Commutable>;
1545 }
1546 multiclass N3VInt_QHSD2 op11_8, bit op4,
1547 InstrItinClass itinD16, InstrItinClass itinD32,
1548 InstrItinClass itinQ16, InstrItinClass itinQ32,
1549 string OpcodeStr, string Dt,
1550 Intrinsic IntOp, bit Commutable = 0>
1551 : N3VInt_QHS2
1552 OpcodeStr, Dt, IntOp, Commutable> {
1553 def v1i64 : N3VDInt
1554 OpcodeStr, !strconcat(Dt, "64"),
1555 v1i64, v1i64, IntOp, Commutable>;
1556 def v2i64 : N3VQInt
1557 OpcodeStr, !strconcat(Dt, "64"),
1558 v2i64, v2i64, IntOp, Commutable>;
1559 }
1560 }
13521561
13531562 // Neon Narrowing 3-register vector intrinsics,
13541563 // source operand element sizes of 16, 32 and 64 bits:
16181827 // imm6 = xxxxxx
16191828 }
16201829
1830 // Same as N2VSh_QHSD, except the instructions have a differnt interpretation of
1831 // the shift amount. This helps the disassembler.
1832 let NSF = NVectorShift2Frm, NSForm = NVectorShift2Frm.Value in {
1833 multiclass N2VSh_QHSD2 op11_8, bit op4,
1834 InstrItinClass itin, string OpcodeStr, string Dt,
1835 SDNode OpNode> {
1836 // 64-bit vector types.
1837 def v8i8 : N2VDSh
1838 OpcodeStr, !strconcat(Dt, "8"), v8i8, OpNode> {
1839 let Inst{21-19} = 0b001; // imm6 = 001xxx
1840 }
1841 def v4i16 : N2VDSh
1842 OpcodeStr, !strconcat(Dt, "16"), v4i16, OpNode> {
1843 let Inst{21-20} = 0b01; // imm6 = 01xxxx
1844 }
1845 def v2i32 : N2VDSh
1846 OpcodeStr, !strconcat(Dt, "32"), v2i32, OpNode> {
1847 let Inst{21} = 0b1; // imm6 = 1xxxxx
1848 }
1849 def v1i64 : N2VDSh
1850 OpcodeStr, !strconcat(Dt, "64"), v1i64, OpNode>;
1851 // imm6 = xxxxxx
1852
1853 // 128-bit vector types.
1854 def v16i8 : N2VQSh
1855 OpcodeStr, !strconcat(Dt, "8"), v16i8, OpNode> {
1856 let Inst{21-19} = 0b001; // imm6 = 001xxx
1857 }
1858 def v8i16 : N2VQSh
1859 OpcodeStr, !strconcat(Dt, "16"), v8i16, OpNode> {
1860 let Inst{21-20} = 0b01; // imm6 = 01xxxx
1861 }
1862 def v4i32 : N2VQSh
1863 OpcodeStr, !strconcat(Dt, "32"), v4i32, OpNode> {
1864 let Inst{21} = 0b1; // imm6 = 1xxxxx
1865 }
1866 def v2i64 : N2VQSh
1867 OpcodeStr, !strconcat(Dt, "64"), v2i64, OpNode>;
1868 // imm6 = xxxxxx
1869 }
1870 }
16211871
16221872 // Neon Shift-Accumulate vector operations,
16231873 // element sizes of 8, 16, 32 and 64 bits:
16961946 def v2i64 : N2VQShIns
16971947 OpcodeStr, "64", v2i64, ShOp>;
16981948 // imm6 = xxxxxx
1949 }
1950
1951 // Same as N2VShIns_QHSD, except the instructions have a differnt interpretation
1952 // of the shift amount. This helps the disassembler.
1953 let NSF = NVectorShift2Frm, NSForm = NVectorShift2Frm.Value in {
1954 multiclass N2VShIns_QHSD2 op11_8, bit op4,
1955 string OpcodeStr, SDNode ShOp> {
1956 // 64-bit vector types.
1957 def v8i8 : N2VDShIns
1958 OpcodeStr, "8", v8i8, ShOp> {
1959 let Inst{21-19} = 0b001; // imm6 = 001xxx
1960 }
1961 def v4i16 : N2VDShIns
1962 OpcodeStr, "16", v4i16, ShOp> {
1963 let Inst{21-20} = 0b01; // imm6 = 01xxxx
1964 }
1965 def v2i32 : N2VDShIns
1966 OpcodeStr, "32", v2i32, ShOp> {
1967 let Inst{21} = 0b1; // imm6 = 1xxxxx
1968 }
1969 def v1i64 : N2VDShIns
1970 OpcodeStr, "64", v1i64, ShOp>;
1971 // imm6 = xxxxxx
1972
1973 // 128-bit vector types.
1974 def v16i8 : N2VQShIns
1975 OpcodeStr, "8", v16i8, ShOp> {
1976 let Inst{21-19} = 0b001; // imm6 = 001xxx
1977 }
1978 def v8i16 : N2VQShIns
1979 OpcodeStr, "16", v8i16, ShOp> {
1980 let Inst{21-20} = 0b01; // imm6 = 01xxxx
1981 }
1982 def v4i32 : N2VQShIns
1983 OpcodeStr, "32", v4i32, ShOp> {
1984 let Inst{21} = 0b1; // imm6 = 1xxxxx
1985 }
1986 def v2i64 : N2VQShIns
1987 OpcodeStr, "64", v2i64, ShOp>;
1988 // imm6 = xxxxxx
1989 }
16991990 }
17001991
17011992 // Neon Shift Long operations,
23282619 // Vector Shifts.
23292620
23302621 // VSHL : Vector Shift
2331 defm VSHLs : N3VInt_QHSD<0, 0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
2332 IIC_VSHLiQ, "vshl", "s", int_arm_neon_vshifts, 0>;
2333 defm VSHLu : N3VInt_QHSD<1, 0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
2334 IIC_VSHLiQ, "vshl", "u", int_arm_neon_vshiftu, 0>;
2622 defm VSHLs : N3VInt_QHSD2<0,0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
2623 IIC_VSHLiQ, "vshl", "s", int_arm_neon_vshifts, 0>;
2624 defm VSHLu : N3VInt_QHSD2<1,0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
2625 IIC_VSHLiQ, "vshl", "u", int_arm_neon_vshiftu, 0>;
23352626 // VSHL : Vector Shift Left (Immediate)
2336 defm VSHLi : N2VSh_QHSD<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl>;
2627 // (disassembly note: this has a different interpretation of the shift amont)
2628 defm VSHLi : N2VSh_QHSD2<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl>;
23372629 // VSHR : Vector Shift Right (Immediate)
23382630 defm VSHRs : N2VSh_QHSD<0, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "s", NEONvshrs>;
23392631 defm VSHRu : N2VSh_QHSD<1, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "u", NEONvshru>;
23402632
23412633 // VSHLL : Vector Shift Left Long
2634 // (disassembly note: this has a different interpretation of the shift amont)
23422635 defm VSHLLs : N2VLSh_QHS<0, 1, 0b1010, 0, 0, 1, "vshll", "s", NEONvshlls>;
2636 // (disassembly note: this has a different interpretation of the shift amont)
23432637 defm VSHLLu : N2VLSh_QHS<1, 1, 0b1010, 0, 0, 1, "vshll", "u", NEONvshllu>;
23442638
23452639 // VSHLL : Vector Shift Left Long (with maximum shift count)
23492643 : N2VLSh
23502644 ResTy, OpTy, OpNode> {
23512645 let Inst{21-16} = op21_16;
2646 let NSF = NVdVmImmVSHLLFrm; // For disassembly.
2647 let NSForm = NVdVmImmVSHLLFrm.Value; // For disassembly.
23522648 }
23532649 def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8",
23542650 v8i16, v8i8, NEONvshlli>;
23622658 NEONvshrn>;
23632659
23642660 // VRSHL : Vector Rounding Shift
2365 defm VRSHLs : N3VInt_QHSD<0,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2366 IIC_VSHLi4Q, "vrshl", "s", int_arm_neon_vrshifts,0>;
2367 defm VRSHLu : N3VInt_QHSD<1,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2368 IIC_VSHLi4Q, "vrshl", "u", int_arm_neon_vrshiftu,0>;
2661 defm VRSHLs : N3VInt_QHSD2<0,0,0b0101,0,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2662 IIC_VSHLi4Q,"vrshl", "s", int_arm_neon_vrshifts,0>;
2663 defm VRSHLu : N3VInt_QHSD2<1,0,0b0101,0,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2664 IIC_VSHLi4Q,"vrshl", "u", int_arm_neon_vrshiftu,0>;
23692665 // VRSHR : Vector Rounding Shift Right
23702666 defm VRSHRs : N2VSh_QHSD<0,1,0b0010,1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs>;
23712667 defm VRSHRu : N2VSh_QHSD<1,1,0b0010,1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru>;
23752671 NEONvrshrn>;
23762672
23772673 // VQSHL : Vector Saturating Shift
2378 defm VQSHLs : N3VInt_QHSD<0,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2379 IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts,0>;
2380 defm VQSHLu : N3VInt_QHSD<1,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2381 IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu,0>;
2674 defm VQSHLs : N3VInt_QHSD2<0,0,0b0100,1,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2675 IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts,0>;
2676 defm VQSHLu : N3VInt_QHSD2<1,0,0b0100,1,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2677 IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu,0>;
23822678 // VQSHL : Vector Saturating Shift Left (Immediate)
2383 defm VQSHLsi : N2VSh_QHSD<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>;
2384 defm VQSHLui : N2VSh_QHSD<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>;
2679 // (disassembly note: this has a different interpretation of the shift amont)
2680 defm VQSHLsi : N2VSh_QHSD2<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>;
2681 // (disassembly note: this has a different interpretation of the shift amont)
2682 defm VQSHLui : N2VSh_QHSD2<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>;
23852683 // VQSHLU : Vector Saturating Shift Left (Immediate, Unsigned)
2386 defm VQSHLsu : N2VSh_QHSD<1,1,0b0110,1, IIC_VSHLi4D, "vqshlu","s",NEONvqshlsu>;
2684 // (disassembly note: this has a different interpretation of the shift amont)
2685 defm VQSHLsu : N2VSh_QHSD2<1,1,0b0110,1, IIC_VSHLi4D, "vqshlu","s",NEONvqshlsu>;
23872686
23882687 // VQSHRN : Vector Saturating Shift Right and Narrow
23892688 defm VQSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "s",
23962695 NEONvqshrnsu>;
23972696
23982697 // VQRSHL : Vector Saturating Rounding Shift
2399 defm VQRSHLs : N3VInt_QHSD<0,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2400 IIC_VSHLi4Q, "vqrshl", "s",
2401 int_arm_neon_vqrshifts, 0>;
2402 defm VQRSHLu : N3VInt_QHSD<1,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2403 IIC_VSHLi4Q, "vqrshl", "u",
2404 int_arm_neon_vqrshiftu, 0>;
2698 defm VQRSHLs : N3VInt_QHSD2<0,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2699 IIC_VSHLi4Q, "vqrshl", "s",
2700 int_arm_neon_vqrshifts, 0>;
2701 defm VQRSHLu : N3VInt_QHSD2<1,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
2702 IIC_VSHLi4Q, "vqrshl", "u",
2703 int_arm_neon_vqrshiftu, 0>;
24052704
24062705 // VQRSHRN : Vector Saturating Rounding Shift Right and Narrow
24072706 defm VQRSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 1, 1, IIC_VSHLi4D, "vqrshrn", "s",
24212720 defm VRSRAu : N2VShAdd_QHSD<1, 1, 0b0011, 1, "vrsra", "u", NEONvrshru>;
24222721
24232722 // VSLI : Vector Shift Left and Insert
2424 defm VSLI : N2VShIns_QHSD<1, 1, 0b0101, 1, "vsli", NEONvsli>;
2723 // (disassembly note: this has a different interpretation of the shift amont)
2724 defm VSLI : N2VShIns_QHSD2<1, 1, 0b0101, 1, "vsli", NEONvsli>;
24252725 // VSRI : Vector Shift Right and Insert
24262726 defm VSRI : N2VShIns_QHSD<1, 1, 0b0100, 1, "vsri", NEONvsri>;
24272727
25172817
25182818 // VMOV : Vector Move (Register)
25192819
2820 // Mark these instructions as 2-register instructions to help the disassembler.
2821 let NSF = NVdVmImmFrm, NSForm = NVdVmImmFrm.Value in {
25202822 def VMOVDneon: N3VX<0, 0, 0b10, 0b0001, 0, 1, (outs DPR:$dst), (ins DPR:$src),
25212823 IIC_VMOVD, "vmov", "$dst, $src", "", []>;
25222824 def VMOVQ : N3VX<0, 0, 0b10, 0b0001, 1, 1, (outs QPR:$dst), (ins QPR:$src),
25232825 IIC_VMOVD, "vmov", "$dst, $src", "", []>;
2826 }
25242827
25252828 // VMOV : Vector Move (Immediate)
25262829
27613064
27623065 // VDUP : Vector Duplicate Lane (from scalar to all elements)
27633066
3067 let NSF = NVdVmImmVDupLaneFrm, NSForm = NVdVmImmVDupLaneFrm.Value in {
27643068 class VDUPLND op19_18, bits<2> op17_16,
27653069 string OpcodeStr, string Dt, ValueType Ty>
27663070 : N2V<0b11, 0b11, op19_18, op17_16, 0b11000, 0, 0,
27743078 (outs QPR:$dst), (ins DPR:$src, nohash_imm:$lane), IIC_VMOVD,
27753079 OpcodeStr, Dt, "$dst, $src[$lane]", "",
27763080 [(set QPR:$dst, (ResTy (NEONvduplane (OpTy DPR:$src), imm:$lane)))]>;
3081 }
27773082
27783083 // Inst{19-16} is partially specified depending on the element size.
27793084
28423147
28433148 // Vector Conversions.
28443149
3150 let NSF = NVdVmImmVCVTFrm, NSForm = NVdVmImmVCVTFrm.Value in {
3151 class N2VDX op24_23, bits<2> op21_20, bits<2> op19_18,
3152 bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,
3153 string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode>
3154 : N2VD
3155 ResTy, OpTy, OpNode>;
3156 class N2VQX op24_23, bits<2> op21_20, bits<2> op19_18,
3157 bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,
3158 string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode>
3159 : N2VQ
3160 ResTy, OpTy, OpNode>;
3161 }
3162
28453163 // VCVT : Vector Convert Between Floating-Point and Integers
2846 def VCVTf2sd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
2847 v2i32, v2f32, fp_to_sint>;
2848 def VCVTf2ud : N2VD<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
2849 v2i32, v2f32, fp_to_uint>;
2850 def VCVTs2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
2851 v2f32, v2i32, sint_to_fp>;
2852 def VCVTu2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
2853 v2f32, v2i32, uint_to_fp>;
2854
2855 def VCVTf2sq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
2856 v4i32, v4f32, fp_to_sint>;
2857 def VCVTf2uq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
2858 v4i32, v4f32, fp_to_uint>;
2859 def VCVTs2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
2860 v4f32, v4i32, sint_to_fp>;
2861 def VCVTu2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
2862 v4f32, v4i32, uint_to_fp>;
3164 def VCVTf2sd : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
3165 v2i32, v2f32, fp_to_sint>;
3166 def VCVTf2ud : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
3167 v2i32, v2f32, fp_to_uint>;
3168 def VCVTs2fd : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
3169 v2f32, v2i32, sint_to_fp>;
3170 def VCVTu2fd : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
3171 v2f32, v2i32, uint_to_fp>;
3172
3173 def VCVTf2sq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
3174 v4i32, v4f32, fp_to_sint>;
3175 def VCVTf2uq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
3176 v4i32, v4f32, fp_to_uint>;
3177 def VCVTs2fq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
3178 v4f32, v4i32, sint_to_fp>;
3179 def VCVTu2fq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
3180 v4f32, v4i32, uint_to_fp>;
28633181
28643182 // VCVT : Vector Convert Between Floating-Point and Fixed-Point.
28653183 def VCVTf2xsd : N2VCvtD<0, 1, 0b1111, 0, 1, "vcvt", "s32.f32",
29443262
29453263 // VEXT : Vector Extract
29463264
3265 let NSF = NVdVnVmImmVectorExtractFrm,
3266 NSForm = NVdVnVmImmVectorExtractFrm.Value in {
29473267 class VEXTd
29483268 : N3V<0,1,0b11,{?,?,?,?},0,0, (outs DPR:$dst),
29493269 (ins DPR:$lhs, DPR:$rhs, i32imm:$index), IIC_VEXTD,
29573277 OpcodeStr, Dt, "$dst, $lhs, $rhs, $index", "",
29583278 [(set QPR:$dst, (Ty (NEONvext (Ty QPR:$lhs),
29593279 (Ty QPR:$rhs), imm:$index)))]>;
3280 }
29603281
29613282 def VEXTd8 : VEXTd<"vext", "8", v8i8>;
29623283 def VEXTd16 : VEXTd<"vext", "16", v4i16>;
29993320 def VZIPq32 : N2VQShuffle<0b10, 0b00011, IIC_VPERMQ3, "vzip", "32">;
30003321
30013322 // Vector Table Lookup and Table Extension.
3323
3324 let NSF = VTBLFrm, NSForm = VTBLFrm.Value in {
30023325
30033326 // VTBL : Vector Table Lookup
30043327 def VTBL1
30553378 [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx4 DPR:$orig, DPR:$tbl1,
30563379 DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>;
30573380 } // hasExtraSrcRegAllocReq = 1
3381
3382 } // End of "let NSF = VTBLFrm, ..."
30583383
30593384 //===----------------------------------------------------------------------===//
30603385 // NEON instructions for single-precision FP math
119119 void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
120120 void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum);
121121 void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum);
122 void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum) {}
122 void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum);
123123 void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum);
124124
125125 void printCPSOptionOperand(const MachineInstr *MI, int OpNum) {}
430430 O << "[" << getRegisterName(MO1.getReg());
431431
432432 if (!MO2.getReg()) {
433 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
433 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
434434 O << ", #"
435 << (char)ARM_AM::getAM2Op(MO3.getImm())
435 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
436436 << ARM_AM::getAM2Offset(MO3.getImm());
437437 O << "]";
438438 return;
439439 }
440440
441441 O << ", "
442 << (char)ARM_AM::getAM2Op(MO3.getImm())
442 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
443443 << getRegisterName(MO2.getReg());
444444
445445 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
457457 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
458458 assert(ImmOffs && "Malformed indexed load / store!");
459459 O << "#"
460 << (char)ARM_AM::getAM2Op(MO2.getImm())
460 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
461461 << ImmOffs;
462462 return;
463463 }
464464
465 O << (char)ARM_AM::getAM2Op(MO2.getImm())
465 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
466466 << getRegisterName(MO1.getReg());
467467
468468 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
489489
490490 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
491491 O << ", #"
492 << (char)ARM_AM::getAM3Op(MO3.getImm())
492 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
493493 << ImmOffs;
494494 O << "]";
495495 }
507507 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
508508 assert(ImmOffs && "Malformed indexed load / store!");
509509 O << "#"
510 << (char)ARM_AM::getAM3Op(MO2.getImm())
510 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
511511 << ImmOffs;
512512 }
513513
552552
553553 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
554554 O << ", #"
555 << (char)ARM_AM::getAM5Op(MO2.getImm())
555 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
556556 << ImmOffs*4;
557557 }
558558 O << "]";
588588
589589 const MachineOperand &MO1 = MI->getOperand(Op);
590590 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
591 O << "[pc, +" << getRegisterName(MO1.getReg()) << "]";
591 O << "[pc, " << getRegisterName(MO1.getReg()) << "]";
592592 }
593593
594594 void
611611 ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) {
612612 // (3 - the number of trailing zeros) is the number of then / else.
613613 unsigned Mask = MI->getOperand(Op).getImm();
614 unsigned CondBit0 = Mask >> 4 & 1;
614615 unsigned NumTZ = CountTrailingZeros_32(Mask);
615616 assert(NumTZ <= 3 && "Invalid IT mask!");
616617 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
617 bool T = (Mask & (1 << Pos)) == 0;
618 bool T = ((Mask >> Pos) & 1) == CondBit0;
618619 if (T)
619620 O << 't';
620621 else
646647 if (MO3.getReg())
647648 O << ", " << getRegisterName(MO3.getReg());
648649 else if (unsigned ImmOffs = MO2.getImm())
649 O << ", #+" << ImmOffs * Scale;
650 O << ", #" << ImmOffs * Scale;
650651 O << "]";
651652 }
652653
668669 const MachineOperand &MO2 = MI->getOperand(Op+1);
669670 O << "[" << getRegisterName(MO1.getReg());
670671 if (unsigned ImmOffs = MO2.getImm())
671 O << ", #+" << ImmOffs*4;
672 O << ", #" << ImmOffs*4;
672673 O << "]";
673674 }
674675
704705
705706 unsigned OffImm = MO2.getImm();
706707 if (OffImm) // Don't print +0.
707 O << ", #+" << OffImm;
708 O << ", #" << OffImm;
708709 O << "]";
709710 }
710711
720721 if (OffImm < 0)
721722 O << ", #-" << -OffImm;
722723 else if (OffImm > 0)
723 O << ", #+" << OffImm;
724 O << ", #" << OffImm;
724725 O << "]";
725726 }
726727
736737 if (OffImm < 0)
737738 O << ", #-" << -OffImm * 4;
738739 else if (OffImm > 0)
739 O << ", #+" << OffImm * 4;
740 O << ", #" << OffImm * 4;
740741 O << "]";
741742 }
742743
748749 if (OffImm < 0)
749750 O << "#-" << -OffImm;
750751 else if (OffImm > 0)
751 O << "#+" << OffImm;
752 O << "#" << OffImm;
753 }
754
755 void ARMAsmPrinter::printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI,
756 int OpNum) {
757 const MachineOperand &MO1 = MI->getOperand(OpNum);
758 int32_t OffImm = (int32_t)MO1.getImm() / 4;
759 // Don't print +0.
760 if (OffImm < 0)
761 O << "#-" << -OffImm * 4;
762 else if (OffImm > 0)
763 O << "#" << OffImm * 4;
752764 }
753765
754766 void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
2727 #undef MachineInstr
2828 #undef ARMAsmPrinter
2929
30 void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
30 static unsigned NextReg(unsigned Reg) {
31 switch (Reg) {
32 case ARM::D0:
33 return ARM::D1;
34 case ARM::D1:
35 return ARM::D2;
36 case ARM::D2:
37 return ARM::D3;
38 case ARM::D3:
39 return ARM::D4;
40 case ARM::D4:
41 return ARM::D5;
42 case ARM::D5:
43 return ARM::D6;
44 case ARM::D6:
45 return ARM::D7;
46 case ARM::D7:
47 return ARM::D8;
48 case ARM::D8:
49 return ARM::D9;
50 case ARM::D9:
51 return ARM::D10;
52 case ARM::D10:
53 return ARM::D11;
54 case ARM::D11:
55 return ARM::D12;
56 case ARM::D12:
57 return ARM::D13;
58 case ARM::D13:
59 return ARM::D14;
60 case ARM::D14:
61 return ARM::D15;
62 case ARM::D15:
63 return ARM::D16;
64 case ARM::D16:
65 return ARM::D17;
66 case ARM::D17:
67 return ARM::D18;
68 case ARM::D18:
69 return ARM::D19;
70 case ARM::D19:
71 return ARM::D20;
72 case ARM::D20:
73 return ARM::D21;
74 case ARM::D21:
75 return ARM::D22;
76 case ARM::D22:
77 return ARM::D23;
78 case ARM::D23:
79 return ARM::D24;
80 case ARM::D24:
81 return ARM::D25;
82 case ARM::D25:
83 return ARM::D26;
84 case ARM::D26:
85 return ARM::D27;
86 case ARM::D27:
87 return ARM::D28;
88 case ARM::D28:
89 return ARM::D29;
90 case ARM::D29:
91 return ARM::D30;
92 case ARM::D30:
93 return ARM::D31;
94
95 default:
96 assert(0 && "Unexpected register enum");
97 }
98 }
99
100 void ARMInstPrinter::printInst(const MCInst *MI) {
101 // Check for MOVs and print canonical forms, instead.
102 if (MI->getOpcode() == ARM::MOVs) {
103 const MCOperand &Dst = MI->getOperand(0);
104 const MCOperand &MO1 = MI->getOperand(1);
105 const MCOperand &MO2 = MI->getOperand(2);
106 const MCOperand &MO3 = MI->getOperand(3);
107
108 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
109 printSBitModifierOperand(MI, 6);
110 printPredicateOperand(MI, 4);
111
112 O << '\t' << getRegisterName(Dst.getReg())
113 << ", " << getRegisterName(MO1.getReg());
114
115 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
116 return;
117
118 O << ", ";
119
120 if (MO2.getReg()) {
121 O << getRegisterName(MO2.getReg());
122 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
123 } else {
124 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
125 }
126 return;
127 }
128
129 // A8.6.123 PUSH
130 if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
131 MI->getOperand(0).getReg() == ARM::SP) {
132 const MCOperand &MO1 = MI->getOperand(2);
133 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
134 O << '\t' << "push";
135 printPredicateOperand(MI, 3);
136 O << '\t';
137 printRegisterList(MI, 5);
138 return;
139 }
140 }
141
142 // A8.6.122 POP
143 if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
144 MI->getOperand(0).getReg() == ARM::SP) {
145 const MCOperand &MO1 = MI->getOperand(2);
146 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
147 O << '\t' << "pop";
148 printPredicateOperand(MI, 3);
149 O << '\t';
150 printRegisterList(MI, 5);
151 return;
152 }
153 }
154
155 // A8.6.355 VPUSH
156 if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
157 MI->getOperand(0).getReg() == ARM::SP) {
158 const MCOperand &MO1 = MI->getOperand(2);
159 if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) {
160 O << '\t' << "vpush";
161 printPredicateOperand(MI, 3);
162 O << '\t';
163 printRegisterList(MI, 5);
164 return;
165 }
166 }
167
168 // A8.6.354 VPOP
169 if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
170 MI->getOperand(0).getReg() == ARM::SP) {
171 const MCOperand &MO1 = MI->getOperand(2);
172 if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) {
173 O << '\t' << "vpop";
174 printPredicateOperand(MI, 3);
175 O << '\t';
176 printRegisterList(MI, 5);
177 return;
178 }
179 }
180
181 printInstruction(MI);
182 }
31183
32184 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
33185 const char *Modifier) {
35187 if (Op.isReg()) {
36188 unsigned Reg = Op.getReg();
37189 if (Modifier && strcmp(Modifier, "dregpair") == 0) {
190 O << '{' << getRegisterName(Reg) << ", "
191 << getRegisterName(NextReg(Reg)) << '}';
192 #if 0
38193 // FIXME: Breaks e.g. ARM/vmul.ll.
39194 assert(0);
40195 /*
43198 O << '{'
44199 << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
45200 << '}';*/
201 #endif
46202 } else if (Modifier && strcmp(Modifier, "lane") == 0) {
47203 assert(0);
48204 /*
55211 O << getRegisterName(Reg);
56212 }
57213 } else if (Op.isImm()) {
58 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
214 bool isCallOp = Modifier && !strcmp(Modifier, "call");
215 assert(isCallOp ||
216 ((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
59217 O << '#' << Op.getImm();
60218 } else {
61219 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
141299 O << "[" << getRegisterName(MO1.getReg());
142300
143301 if (!MO2.getReg()) {
144 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
302 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
145303 O << ", #"
146 << (char)ARM_AM::getAM2Op(MO3.getImm())
147 << ARM_AM::getAM2Offset(MO3.getImm());
304 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
305 << ARM_AM::getAM2Offset(MO3.getImm());
148306 O << "]";
149307 return;
150308 }
151309
152310 O << ", "
153 << (char)ARM_AM::getAM2Op(MO3.getImm())
154 << getRegisterName(MO2.getReg());
311 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
312 << getRegisterName(MO2.getReg());
155313
156314 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
157315 O << ", "
168326 if (!MO1.getReg()) {
169327 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
170328 assert(ImmOffs && "Malformed indexed load / store!");
171 O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
172 return;
173 }
174
175 O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
329 O << '#'
330 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
331 << ImmOffs;
332 return;
333 }
334
335 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
336 << getRegisterName(MO1.getReg());
176337
177338 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
178339 O << ", "
195356
196357 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
197358 O << ", #"
198 << (char)ARM_AM::getAM3Op(MO3.getImm())
199 << ImmOffs;
359 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
360 << ImmOffs;
200361 O << ']';
201362 }
202363
213374
214375 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
215376 assert(ImmOffs && "Malformed indexed load / store!");
216 O << "#"
217 << (char)ARM_AM::getAM3Op(MO2.getImm())
218 << ImmOffs;
377 O << '#'
378 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
379 << ImmOffs;
219380 }
220381
221382
258419
259420 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
260421 O << ", #"
261 << (char)ARM_AM::getAM5Op(MO2.getImm())
422 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
262423 << ImmOffs*4;
263424 }
264425 O << "]";
297458
298459 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
299460 O << "{";
300 // Always skip the first operand, it's the optional (and implicit writeback).
301 for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
302 if (i != OpNum+1) O << ", ";
461 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
462 if (i != OpNum) O << ", ";
303463 O << getRegisterName(MI->getOperand(i).getReg());
304464 }
305465 O << "}";
466 }
467
468 void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {
469 const MCOperand &Op = MI->getOperand(OpNum);
470 unsigned option = Op.getImm();
471 unsigned mode = option & 31;
472 bool changemode = option >> 5 & 1;
473 unsigned AIF = option >> 6 & 7;
474 unsigned imod = option >> 9 & 3;
475 if (imod == 2)
476 O << "ie";
477 else if (imod == 3)
478 O << "id";
479 O << '\t';
480 if (imod > 1) {
481 if (AIF & 4) O << 'a';
482 if (AIF & 2) O << 'i';
483 if (AIF & 1) O << 'f';
484 if (AIF > 0 && changemode) O << ", ";
485 }
486 if (changemode)
487 O << '#' << mode;
488 }
489
490 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {
491 const MCOperand &Op = MI->getOperand(OpNum);
492 unsigned Mask = Op.getImm();
493 if (Mask) {
494 O << '_';
495 if (Mask & 8) O << 'f';
496 if (Mask & 4) O << 's';
497 if (Mask & 2) O << 'x';
498 if (Mask & 1) O << 'c';
499 }
500 }
501
502 void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum){
503 const MCOperand &Op = MI->getOperand(OpNum);
504 O << '#';
505 if (Op.getImm() < 0)
506 O << '-' << (-Op.getImm() - 1);
507 else
508 O << Op.getImm();
306509 }
307510
308511 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
346549 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) {
347550 O << "#" << MI->getOperand(OpNum).getImm() * 4;
348551 }
552
553 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum) {
554 // (3 - the number of trailing zeros) is the number of then / else.
555 unsigned Mask = MI->getOperand(OpNum).getImm();
556 unsigned CondBit0 = Mask >> 4 & 1;
557 unsigned NumTZ = CountTrailingZeros_32(Mask);
558 assert(NumTZ <= 3 && "Invalid IT mask!");
559 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
560 bool T = ((Mask >> Pos) & 1) == CondBit0;
561 if (T)
562 O << 't';
563 else
564 O << 'e';
565 }
566 }
567
568 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op)
569 {
570 const MCOperand &MO1 = MI->getOperand(Op);
571 const MCOperand &MO2 = MI->getOperand(Op+1);
572 O << "[" << getRegisterName(MO1.getReg());
573 O << ", " << getRegisterName(MO2.getReg()) << "]";
574 }
575
576 void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
577 unsigned Scale) {
578 const MCOperand &MO1 = MI->getOperand(Op);
579 const MCOperand &MO2 = MI->getOperand(Op+1);
580 const MCOperand &MO3 = MI->getOperand(Op+2);
581
582 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
583 printOperand(MI, Op);
584 return;
585 }
586
587 O << "[" << getRegisterName(MO1.getReg());
588 if (MO3.getReg())
589 O << ", " << getRegisterName(MO3.getReg());
590 else if (unsigned ImmOffs = MO2.getImm())
591 O << ", #" << ImmOffs * Scale;
592 O << "]";
593 }
594
595 void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op)
596 {
597 printThumbAddrModeRI5Operand(MI, Op, 1);
598 }
599
600 void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op)
601 {
602 printThumbAddrModeRI5Operand(MI, Op, 2);
603 }
604
605 void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op)
606 {
607 printThumbAddrModeRI5Operand(MI, Op, 4);
608 }
609
610 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI,unsigned Op) {
611 const MCOperand &MO1 = MI->getOperand(Op);
612 const MCOperand &MO2 = MI->getOperand(Op+1);
613 O << "[" << getRegisterName(MO1.getReg());
614 if (unsigned ImmOffs = MO2.getImm())
615 O << ", #" << ImmOffs*4;
616 O << "]";
617 }
618
619 void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum) {
620 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
621 if (MI->getOpcode() == ARM::t2TBH)
622 O << ", lsl #1";
623 O << ']';
624 }
625
626 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
627 // register with shift forms.
628 // REG 0 0 - e.g. R5
629 // REG IMM, SH_OPC - e.g. R5, LSL #3
630 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum) {
631 const MCOperand &MO1 = MI->getOperand(OpNum);
632 const MCOperand &MO2 = MI->getOperand(OpNum+1);
633
634 unsigned Reg = MO1.getReg();
635 O << getRegisterName(Reg);
636
637 // Print the shift opc.
638 O << ", "
639 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
640 << " ";
641
642 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
643 O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
644 }
645
646 void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI,
647 unsigned OpNum) {
648 const MCOperand &MO1 = MI->getOperand(OpNum);
649 const MCOperand &MO2 = MI->getOperand(OpNum+1);
650
651 O << "[" << getRegisterName(MO1.getReg());
652
653 unsigned OffImm = MO2.getImm();
654 if (OffImm) // Don't print +0.
655 O << ", #" << OffImm;
656 O << "]";
657 }
658
659 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
660 unsigned OpNum) {
661 const MCOperand &MO1 = MI->getOperand(OpNum);
662 const MCOperand &MO2 = MI->getOperand(OpNum+1);
663
664 O << "[" << getRegisterName(MO1.getReg());
665
666 int32_t OffImm = (int32_t)MO2.getImm();
667 // Don't print +0.
668 if (OffImm < 0)
669 O << ", #-" << -OffImm;
670 else if (OffImm > 0)
671 O << ", #" << OffImm;
672 O << "]";
673 }
674
675 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
676 unsigned OpNum) {
677 const MCOperand &MO1 = MI->getOperand(OpNum);
678 const MCOperand &MO2 = MI->getOperand(OpNum+1);
679
680 O << "[" << getRegisterName(MO1.getReg());
681
682 int32_t OffImm = (int32_t)MO2.getImm() / 4;
683 // Don't print +0.
684 if (OffImm < 0)
685 O << ", #-" << -OffImm * 4;
686 else if (OffImm > 0)
687 O << ", #" << OffImm * 4;
688 O << "]";
689 }
690
691 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
692 unsigned OpNum) {
693 const MCOperand &MO1 = MI->getOperand(OpNum);
694 int32_t OffImm = (int32_t)MO1.getImm();
695 // Don't print +0.
696 if (OffImm < 0)
697 O << "#-" << -OffImm;
698 else if (OffImm > 0)
699 O << "#" << OffImm;
700 }
701
702 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
703 unsigned OpNum) {
704 const MCOperand &MO1 = MI->getOperand(OpNum);
705 int32_t OffImm = (int32_t)MO1.getImm() / 4;
706 // Don't print +0.
707 if (OffImm < 0)
708 O << "#-" << -OffImm * 4;
709 else if (OffImm > 0)
710 O << "#" << OffImm * 4;
711 }
712
713 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
714 unsigned OpNum) {
715 const MCOperand &MO1 = MI->getOperand(OpNum);
716 const MCOperand &MO2 = MI->getOperand(OpNum+1);
717 const MCOperand &MO3 = MI->getOperand(OpNum+2);
718
719 O << "[" << getRegisterName(MO1.getReg());
720
721 assert(MO2.getReg() && "Invalid so_reg load / store address!");
722 O << ", " << getRegisterName(MO2.getReg());
723
724 unsigned ShAmt = MO3.getImm();
725 if (ShAmt) {
726 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
727 O << ", lsl #" << ShAmt;
728 }
729 O << "]";
730 }
731
732 void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum) {
733 O << '#' << MI->getOperand(OpNum).getImm();
734 }
735
736 void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum) {
737 O << '#' << MI->getOperand(OpNum).getImm();
738 }
739
5353 void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum);
5454
5555 void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum);
56 void printThumbITMask(const MCInst *MI, unsigned OpNum) {}
57 void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum) {}
56 void printThumbITMask(const MCInst *MI, unsigned OpNum);
57 void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum);
5858 void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum,
59 unsigned Scale) {}
60 void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum) {}
61 void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum) {}
62 void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum) {}
63 void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum) {}
59 unsigned Scale);
60 void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum);
61 void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum);
62 void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum);
63 void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum);
6464
65 void printT2SOOperand(const MCInst *MI, unsigned OpNum) {}
66 void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum) {}
67 void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum) {}
68 void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum) {}
69 void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum) {}
70 void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum) {}
71 void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum) {}
65 void printT2SOOperand(const MCInst *MI, unsigned OpNum);
66 void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum);
67 void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum);
68 void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum);
69 void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum);
70 void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum);
71 void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum);
7272
73 void printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {}
74 void printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {}
75 void printNegZeroOperand(const MCInst *MI, unsigned OpNum) {}
73 void printCPSOptionOperand(const MCInst *MI, unsigned OpNum);
74 void printMSRMaskOperand(const MCInst *MI, unsigned OpNum);
75 void printNegZeroOperand(const MCInst *MI, unsigned OpNum);
7676 void printPredicateOperand(const MCInst *MI, unsigned OpNum);
7777 void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum);
7878 void printSBitModifierOperand(const MCInst *MI, unsigned OpNum);
8181 const char *Modifier);
8282 void printJTBlockOperand(const MCInst *MI, unsigned OpNum) {}
8383 void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {}
84 void printTBAddrMode(const MCInst *MI, unsigned OpNum) {}
84 void printTBAddrMode(const MCInst *MI, unsigned OpNum);
8585 void printNoHashImmediate(const MCInst *MI, unsigned OpNum);
86 void printVFPf32ImmOperand(const MCInst *MI, int OpNum) {}
87 void printVFPf64ImmOperand(const MCInst *MI, int OpNum) {}
86 void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum);
87 void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum);
8888 void printHex8ImmOperand(const MCInst *MI, int OpNum) {}
8989 void printHex16ImmOperand(const MCInst *MI, int OpNum) {}
9090 void printHex32ImmOperand(const MCInst *MI, int OpNum) {}
33
44 define arm_aapcscc void @g() {
55 entry:
6 ;CHECK: [sp, #+8]
7 ;CHECK: [sp, #+12]
6 ;CHECK: [sp, #8]
7 ;CHECK: [sp, #12]
88 ;CHECK: [sp]
99 tail call arm_aapcscc void (i8*, ...)* @f(i8* getelementptr ([1 x i8]* @.str, i32 0, i32 0), i32 1, double 2.000000e+00, i32 3, double 4.000000e+00)
1010 ret void
55 entry:
66 ;CHECK: sub sp, sp, #4
77 ;CHECK: add r{{[0-9]+}}, sp, #8
8 ;CHECK: str r{{[0-9]+}}, [sp], #+4
8 ;CHECK: str r{{[0-9]+}}, [sp], #4
99 ;CHECK: bx lr
1010 %ap = alloca i8*, align 4
1111 %ap1 = bitcast i8** %ap to i8*
44
55 define void @test(i32* %P, i32 %A, i32 %i) nounwind {
66 entry:
7 ; CHECK: str r1, [{{r.*}}, +{{r.*}}, lsl #2]
7 ; CHECK: str r1, [{{r.*}}, {{r.*}}, lsl #2]
88 icmp eq i32 %i, 0 ; :0 [#uses=1]
99 br i1 %0, label %return, label %bb
1010
4040 ; DarwinPIC: _test1:
4141 ; DarwinPIC: ldr r0, LCPI1_0
4242 ; DarwinPIC: LPC1_0:
43 ; DarwinPIC: ldr r0, [pc, +r0]
43 ; DarwinPIC: ldr r0, [pc, r0]
4444 ; DarwinPIC: ldr r0, [r0]
4545 ; DarwinPIC: bx lr
4646
6262
6363 ; LinuxPIC: .LPC1_0:
6464 ; LinuxPIC: add r0, pc, r0
65 ; LinuxPIC: ldr r0, [r1, +r0]
65 ; LinuxPIC: ldr r0, [r1, r0]
6666 ; LinuxPIC: ldr r0, [r0]
6767 ; LinuxPIC: bx lr
6868
99 ;V6: ldrd r2, [r2]
1010
1111 ;V5: ldr r3, [r2]
12 ;V5: ldr r2, [r2, #+4]
12 ;V5: ldr r2, [r2, #4]
1313
1414 ;EABI: ldr r3, [r2]
15 ;EABI: ldr r2, [r2, #+4]
15 ;EABI: ldr r2, [r2, #4]
1616
1717 %0 = load i64** @b, align 4
1818 %1 = load i64* %0, align 4
0 ; RUN: llc < %s -mtriple=arm-linux-gnu | grep {str.*\\!}
1 ; RUN: llc < %s -mtriple=arm-linux-gnu | grep {ldr.*\\\[.*\], #+4}
1 ; RUN: llc < %s -mtriple=arm-linux-gnu | grep {ldr.*\\\[.*\], #4}
22
33 @b = external global i64*
44
66
77 define i32 @f() {
88 ; CHECK-NONPIC: f:
9 ; CHECK-NONPIC: ldr {{r.}}, [pc, +{{r.}}]
9 ; CHECK-NONPIC: ldr {{r.}}, [pc, {{r.}}]
1010 ; CHECK-NONPIC: i(gottpoff)
1111 ; CHECK-PIC: f:
1212 ; CHECK-PIC: __tls_get_addr
1717
1818 define i32* @g() {
1919 ; CHECK-NONPIC: g:
20 ; CHECK-NONPIC: ldr {{r.}}, [pc, +{{r.}}]
20 ; CHECK-NONPIC: ldr {{r.}}, [pc, {{r.}}]
2121 ; CHECK-NONPIC: i(gottpoff)
2222 ; CHECK-PIC: g:
2323 ; CHECK-PIC: __tls_get_addr
2121
2222 define arm_apcscc %union.rec* @Manifest(%union.rec* %x, %union.rec* %env, %struct.STYLE* %style, %union.rec** %bthr, %union.rec** %fthr, %union.rec** %target, %union.rec** %crs, i32 %ok, i32 %need_expand, %union.rec** %enclose, i32 %fcr) nounwind {
2323 entry:
24 ; CHECK: ldr.w r9, [r7, #+28]
24 ; CHECK: ldr.w r9, [r7, #28]
2525 %xgaps.i = alloca [32 x %union.rec*], align 4 ; <[32 x %union.rec*]*> [#uses=0]
2626 %ycomp.i = alloca [32 x %union.rec*], align 4 ; <[32 x %union.rec*]*> [#uses=0]
2727 br i1 false, label %bb, label %bb20
4949 bb420: ; preds = %bb20, %bb20
5050 ; CHECK: bb420
5151 ; CHECK: str r{{[0-7]}}, [sp]
52 ; CHECK: str r{{[0-7]}}, [sp, #+4]
53 ; CHECK: str r{{[0-7]}}, [sp, #+8]
54 ; CHECK: str{{(.w)?}} r{{[0-9]+}}, [sp, #+24]
52 ; CHECK: str r{{[0-7]}}, [sp, #4]
53 ; CHECK: str r{{[0-7]}}, [sp, #8]
54 ; CHECK: str{{(.w)?}} r{{[0-9]+}}, [sp, #24]
5555 store %union.rec* null, %union.rec** @zz_hold, align 4
5656 store %union.rec* null, %union.rec** @zz_res, align 4
5757 store %union.rec* %x, %union.rec** @zz_hold, align 4
1010 define i32 @f2(i32* %v) {
1111 entry:
1212 ; CHECK: f2:
13 ; CHECK: ldr.w r0, [r0, #+4092]
13 ; CHECK: ldr.w r0, [r0, #4092]
1414 %tmp2 = getelementptr i32* %v, i32 1023
1515 %tmp = load i32* %tmp2
1616 ret i32 %tmp
1010 define i16 @f2(i16* %v) {
1111 entry:
1212 ; CHECK: f2:
13 ; CHECK: ldrh.w r0, [r0, #+2046]
13 ; CHECK: ldrh.w r0, [r0, #2046]
1414 %tmp2 = getelementptr i16* %v, i16 1023
1515 %tmp = load i16* %tmp2
1616 ret i16 %tmp
88
99 define i32 @f2(i32 %a, i32* %v) {
1010 ; CHECK: f2:
11 ; CHECK: str.w r0, [r1, #+4092]
11 ; CHECK: str.w r0, [r1, #4092]
1212 %tmp2 = getelementptr i32* %v, i32 1023
1313 store i32 %a, i32* %tmp2
1414 ret i32 %a
11
22 define void @test1(i32* %X, i32* %A, i32** %dest) {
33 ; CHECK: test1
4 ; CHECK: str r1, [r0, #+16]!
4 ; CHECK: str r1, [r0, #16]!
55 %B = load i32* %A ; [#uses=1]
66 %Y = getelementptr i32* %X, i32 4 ; [#uses=2]
77 store i32 %B, i32* %Y
1111
1212 define i16* @test2(i16* %X, i32* %A) {
1313 ; CHECK: test2
14 ; CHECK: strh r1, [r0, #+8]!
14 ; CHECK: strh r1, [r0, #8]!
1515 %B = load i32* %A ; [#uses=1]
1616 %Y = getelementptr i16* %X, i32 4 ; [#uses=2]
1717 %tmp = trunc i32 %B to i16 ; [#uses=1]
88
99 define i8 @f2(i8 %a, i8* %v) {
1010 ; CHECK: f2:
11 ; CHECK: strb.w r0, [r1, #+4092]
11 ; CHECK: strb.w r0, [r1, #4092]
1212 %tmp2 = getelementptr i8* %v, i32 4092
1313 store i8 %a, i8* %tmp2
1414 ret i8 %a
88
99 define i16 @f2(i16 %a, i16* %v) {
1010 ; CHECK: f2:
11 ; CHECK: strh.w r0, [r1, #+4092]
11 ; CHECK: strh.w r0, [r1, #4092]
1212 %tmp2 = getelementptr i16* %v, i32 2046
1313 store i16 %a, i16* %tmp2
1414 ret i16 %a